Code and Life

Programming, electronics and other cool tech stuff

Supported by

Supported by Picotech

AVR ATtiny USB Tutorial Part 3

This is the third part of my USB tutorial for ATtiny2313 and V-USB library. In the second part we got the breadboard setup more or less covered, and now is the time for actual code! This will most likely be the longest of the three parts, so let’s get started.

Adding V-USB as a part of your project

First, we will download the latest version V-USB library from OBdev. Head to the Downloads-section and get the latest .zip – I got

Unzip the archive and copy the usbdrv subfolder to your project folder (the whole folder, not just contents). Go to the subfolder and make a copy of usbconfig-prototype.h with the name usbconfig.h. Locate the #define lines for IO port and port bits and clock rate, and update them as necessary to reflect our configuration where D+ is in PD2 and D- in PD3 and clock rate is 12 MHz:

#define USB_CFG_DMINUS_BIT      3
#define USB_CFG_DPLUS_BIT       2
#define USB_CFG_CLOCK_KHZ       12000

It’s also a good idea to ensure that V-USB tells the computer that it is powered via USB (i.e. not self powered) and takes maximum of 50 mA of power (defaults in my version is USB power, 100 mA max.):

#define USB_CFG_IS_SELF_POWERED         0
#define USB_CFG_MAX_BUS_POWER           50

We will be using OBdev’s licenced vendor and device IDs, so they don’t need to be changed (note that this also means my tutorial will fall under GPL, including the schematic in part 2). But we do want to customize the vendor name and device name (note the backward slash in vendor name string used to split the #define to two lines so it fits into this blog post):

#define  USB_CFG_VENDOR_ID       0xc0, 0x16 /* = 0x16c0 */
#define  USB_CFG_DEVICE_ID       0xdc, 0x05 /* = 0x05dc */

#define USB_CFG_DEVICE_VERSION  0x00, 0x01

#define USB_CFG_VENDOR_NAME     'c', 'o', 'd', 'e', 'a', 'n', 'd', 'l', \\
                                'i', 'f', 'e', '.', 'c', 'o', 'm'

#define USB_CFG_DEVICE_NAME     'U', 'S', 'B', 'e', 'x', 'a', 'm', 'p', 'l', 'e'

The usbconfig.h header file is well documented so you may want to read the rest of the options to get an idea what the library can can do. Now the only thing missing is the actual C file to use the library. Here is the barebones version of main.c we’ll start with:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>

#include "usbdrv.h"

#define F_CPU 12000000L
#include <util/delay.h>

USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) {
	return 0; // do nothing for now

int main() {
	uchar i;

    wdt_enable(WDTO_1S); // enable 1s watchdog timer

    usbDeviceDisconnect(); // enforce re-enumeration
    for(i = 0; i<250; i++) { // wait 500 ms
        wdt_reset(); // keep the watchdog happy
    sei(); // Enable interrupts after re-enumeration
    while(1) {
        wdt_reset(); // keep the watchdog happy
    return 0;

The code should be pretty straightforward to understand:

  • Include the usbdrv.h to access V-USB functions
  • Implement usbFunctionSetup() to handle USB requests (we’ll do that soon)
  • In the main function, set up a 1 second watchdog timer that resets the microcontroller if 1000 milliseconds pass without a call to wdt_reset()
  • Call usbInit() to initialize the V-USB library
  • Enforce USB device re-enumeration using usbDeviceDisconnect(), a 500 ms delay (while calling the watchdog reset every 2 ms) and usbDeviceConnect()
  • Enable interrupts
  • Loop forever while calling the watchdog reset and usbPoll()

The reason we are using the watchdog timer is, that our code might for some reason freeze (for example, corrupt data is read and a bug or eternal loop occurs) and the USB device would then stop responding. In this case, the wdt_reset() gets no longer called and after 1 second, the watchdog timer automatically resets our ATtiny, and the program execution starts again (like you’d just resetted the circuit yourself). While this is not absolutely necessary, it is a good practice and saves the user from unplugging and replugging the device if something strange happens.

Another thing you may wonder is why the disconnect/delay/connect -procedure is needed at all. This is because the host PC can remember the identifier assigned to a USB device even if our device resets and forgets that identifier. By enforcing re-enumeration we make sure that both the host PC and our device have the same ID used to communicate over the USB bus.

Now let’s see if we can get it all to compile. The easiest way is to use my ready-made Makefile which also contains the necessary statements for our PC side command-line client. Put the makefile to your project folder and run make main.hex too see if it works. This way, you also see the actual commands the Makefile is used to run – there is nothing special with V-USB, the main things you need to remember is to have -Iusbdrv in place for the compiler to find the .h files from usbdrv folder, and then just having the three additional object files (usbdrv.o, oddebug.o, usbdrvasm.o) put into the same .elf file along with main.o.

Responding to USB control messages

Before we head to PC side code, let’s make our device firmware respond to two basic commands sent via USB: Turning a LED on and off. USB communication is initiated from host side and so-called control messages are sent to make USB device return it’s name or any other desired function. The specification also has room for vendor-specific control messages. Let’s define two such messages:

#define USB_LED_OFF 0
#define USB_LED_ON  1

Now V-USB library automatically calls our usbFunctionSetup() method when it receives a vendor-specific control message. The parameter is a 8-byte buffer actually containing a structure called usbRequest_t that is defined in usbdrv.h. I suggest you to check that definition out. At this point we are interested in the bRequest property that will either be 0 (USB_LED_OFF) or 1 (USB_LED_ON) – we will shortly see how our command-line client on PC side will generate these control requests, so there is nothing magical happening here – we just send a request from PC side and interpret it on the other side. Here’s the modified function to turn the LED on or off:

// this gets called when custom control message is received
USB_PUBLIC uchar usbFunctionSetup(uchar data[8]) {
    usbRequest_t *rq = (void *)data; // cast data to correct type
    switch(rq->bRequest) { // custom command is in the bRequest field
    case USB_LED_ON:
        PORTB |= 1; // turn LED on
        return 0;
    case USB_LED_OFF: 
        PORTB &= ~1; // turn LED off
        return 0;

    return 0; // should not get here

Of course for this to work we need to set PB0 as output in the beginning of main() (I suggest just after the “uchar i;” line):

    DDRB = 1; // PB0 as output

Now we’re ready to deploy our code to the chip. Just call make flash and the dependencies should take care of recompiling the main code file automatically.

Windows driver hell

Now if you are doing this project on a Linux box, congratulations, you likely can just get LibUSB and compile the command-line client to talk to your new device. On Windows, however, you will need a custom device driver. Especially nasty was the fact that older example projects on V-USB site don’t work with 64-bit Windows 7 at all. For this reason, I’ll outline the basic steps for creating and installing your own driver.

Now immediately after you have flashed the ATtiny you should hear the standard Windows fanfare di-dum sound that tells a new USB device has been plugged in. Windows will look for a driver and most likely fail. This is where libusb-win32 comes to the rescue:

  1. Go to the libusb-win32 home page (google if it the above link doesn’t work)
  2. Locate the heading “Device driver installation” and follow the instructions to download the latest version. I used Unzip to a subfolder called “libusb” in the project folder.
  3. Run the INF-wizard using the instructions, put the installer somewhere you like (I recommend a new driver-subfolder in your project folder)
  4. Easiest way to install the driver is to do it as the final step of INF-wizard, there’s a button for it
  5. Replug your device and pray for the best

I could have a separate tutorial covering my trial-and-error methods of getting the USB device driver to install and work. I hope you have better luck. In case of problems, here are some helpful tips:

  • You can use Windows Device Manager to uninstall wrong drivers for your device, or if you get and “Unknown device”, update drivers for the device
  • Select “Browse my computer for driver software” and point Windows manually for correct location. Do not mind any “drivers not certified” -alerts, to go through them
  • Sometimes Windows manages to cache the device in a certain port and no matter how many times you unplug and replug it, it gets recognized wrong. Changing USB port or switching even to a different hub (e.g. from computer case front to back) helped me in some cases
  • Restarting the machine or googling for tools to reset USB cache may help, too :)

This is what the INF-wizard (located in the bin-subfolder of libusb) looks like if you are lucky (USBexample device visible):

This is what you can also enter manually if you are not so lucky:

After clicking Next, you get to save your generated driver to a folder. It’s a good idea to use “Install now…” to avoid installing the drivers manually. My installation hanged 50 % of the time (needed to wait 5 minutes for the installer to exit), but the driver still seemed to install OK.

Command-line client

Congratulations! We are almost there! Now we only need to prepare the host-side software. For compiling it, I recommend the GNU C compiler gcc from MinGW project and the MSYS tools that you should be able to install along with it, but probably Visual C and others work just fine. MinGW installer is really hard to locate (big thumbs down for the wiki authors on usability), but currently trial and error should eventually get you here.

We already installed libusb-win32 in the previous section, and the needed library and header files are all there. Just copy (or rename) the oddly named lusb0_usb.h to usb.h in the libusb/include folder and we’re good to go.

First thing we’ll need to do is to have a little helper function to decipher USB descriptor strings used for vendor name and device name. For this and also later for communicating with our device, we will use [usb_control_msg()]( function provided by libusb. You basically pass the device handle, direction of message (USB_ENDPOINT_IN for device to host and USB_ENDPOINT_OUT for host to device) and other information used to define the recipient and direction, and the control message request, index and value codes, as well as a buffer for input/output, buffer size and maximum timeout for the call.

For those who want to understand the control messages better, I warmly recommend the surprisingly user-friendly USB 2.0 specification. The part on control messages starts on page 248 and the first table concerning this should be Table 9-2. You can find the download link for the spec from part 1 of this tutorial. The specification is rather simple and defined constant values closely reflect the #defines in libusb so you should understand everything rather well just by comparing the spec and my example code.

If you wonder what the rest of our helper function does after calling usb_control_msg, it’s basically checking the return value and response length, and converting it from UTF16-LE to Latin1 (same as ASCII if there’s no special characters). The USB descriptor return format is strictly defined to remove any possibilities for interpretation. This is all explained in chapter 9.5 of the USB specification. So here’s the helper function (it’s basically a slightly revised version of the one used in V-USB PowerSwitch example):

/* Used to get descriptor strings for device identification */
static int usbGetDescriptorString(usb_dev_handle *dev, int index, int langid, 
                                  char *buf, int buflen) {
    char buffer[256];
    int rval, i;

    // make standard request GET_DESCRIPTOR, type string and given index 
    // (e.g. dev->iProduct)
    rval = usb_control_msg(dev, 
        USB_REQ_GET_DESCRIPTOR, (USB_DT_STRING << 8) + index, langid, 
        buffer, sizeof(buffer), 1000);

    if(rval < 0) // error
        return rval;

    // rval should be bytes read, but buffer[0] contains the actual response size
    if((unsigned char)buffer[0] < rval)
        rval = (unsigned char)buffer[0]; // string is shorter than bytes read

    if(buffer[1] != USB_DT_STRING) // second byte is the data type
        return 0; // invalid return type

    // we're dealing with UTF-16LE here so actual chars is half of rval,
    // and index 0 doesn't count
    rval /= 2;

    /* lossy conversion to ISO Latin1 */
    for(i = 1; i < rval && i < buflen; i++) {
        if(buffer[2 * i + 1] == 0)
            buf[i-1] = buffer[2 * i];
            buf[i-1] = '?'; /* outside of ISO Latin1 range */
    buf[i-1] = 0;

    return i-1;

Now we can use this helper function when we iterate over USB devices to recognize our own device with vendor name “” and device name “USBexample”. The libusb-win32 API documentation gives us a good starting point in the examples section. I won’t be hand-holding you too much on this function, the basic logic is just to loop through every USB bus and every USB device in them, open a device and ask it’s vendor and device name, return it if it matches or close and proceed to next one if it does not:

static usb_dev_handle * usbOpenDevice(int vendor, char *vendorName, 
                                      int product, char *productName) {
    struct usb_bus *bus;
    struct usb_device *dev;
    char devVendor[256], devProduct[256];

    usb_dev_handle * handle = NULL;


    for(bus=usb_get_busses(); bus; bus=bus->next) {
        for(dev=bus->devices; dev; dev=dev->next) {			
            if(dev->descriptor.idVendor != vendor ||
               dev->descriptor.idProduct != product)

            /* we need to open the device in order to query strings */
            if(!(handle = usb_open(dev))) {
                fprintf(stderr, "Warning: cannot open USB device: %s\n",

            /* get vendor name */
            if(usbGetDescriptorString(handle, dev->descriptor.iManufacturer, 
                                      0x0409, devVendor, sizeof(devVendor)) < 0) {
                        "Warning: cannot query manufacturer for device: %s\n", 

            /* get product name */
            if(usbGetDescriptorString(handle, dev->descriptor.iProduct, 
                                      0x0409, devProduct, sizeof(devVendor)) < 0) {
                        "Warning: cannot query product for device: %s\n", 

            if(strcmp(devVendor, vendorName) == 0 && 
               strcmp(devProduct, productName) == 0)
                return handle;

    return NULL;

Oh and the 0x0409 is the language code for English, this is also found from the USB specification. Note how the vendor and device names need to be fetched using our helper function – the standard device descriptor in dev only tells the parameter values we need to use for usbGetDescriptorString() to get them (fields iManufacturer and iProduct). This is of course understandable as device descriptor is constant length but the vendor and device names have varying length.

Now that we got past all the sillyness of helper functions to scan all USB devices and return their specially formatted descriptor messages in order to get one simple device handle, the rest of the code is very straightforward. Only thing making the USB communication different from standard structure of accessing a file are the calls to usb_control_msg(), otherwise the general structure of open / do stuff / close applies:

int main(int argc, char **argv) {
    usb_dev_handle *handle = NULL;
    int nBytes = 0;
    char buffer[256];

    if(argc < 2) {
        printf("usbtext.exe on\\n");
        printf("usbtext.exe off\\n");

    handle = usbOpenDevice(0x16C0, "", 0x05DC, "USBexample");

    if(handle == NULL) {
        fprintf(stderr, "Could not find USB device!\n");

    if(strcmp(argv[1], "on") == 0) {
        nBytes = usb_control_msg(handle, 
            USB_LED_ON, 0, 0, (char *)buffer, sizeof(buffer), 5000);
    } else if(strcmp(argv[1], "off") == 0) {
        nBytes = usb_control_msg(handle, 
            USB_LED_OFF, 0, 0, (char *)buffer, sizeof(buffer), 5000);

    if(nBytes < 0)
        fprintf(stderr, "USB error: %s\n", usb_strerror());


    return 0;

Note that the second parameter for usb_control_msg now uses USB_TYPE_VENDOR to indicate we are sending a vendor-specific control message. You can also see that the request, value and index parameters (here USB_LED_ON/OFF, 0, 0) can be freely used to communicate with our code on device side.

You can grab the complete code for usbtest.c from project zip file with two #defines that match the ones in main.c and compile with make usbtest.exe (actually just “make” suffices, as usbtest.exe is one of the default targets). Now you should be able to turn the LED on and off using commands “usbtest on” and “usbtest off”. Note again that you need MinGW installed and “gcc” working in order to do this. The full compile command that “make” runs is:

gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb

Wow! That is all. I think this is enough for anyone to grasp in a single reading, so I will be splitting additional V-USB tricks into a fourth part of this tutorial that I will write later. Spending 5 hours in one setting to write this one is enough. :)

Proceed to the next part of this tutorial



A very good tutorial! The led blinks :-) :-) I am just wondering how to pass an integer to the MCU ATtiny? I saw there is a variable wValue that is uint16, but somehow it doesn’t work… Can you help me?




Thanks! The two additional parameter values to usb_control_msg that are 0, 0 in the example should be able to transmit any two 16-bit integers to your ATtiny. For example, try

nBytes = usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_IN, USB_LED_ON, 123, 234, (char *)buffer, sizeof(buffer), 5000);

The 123 and 234 should be visible on ATtiny side also, in wValue and the other …Index fields. I’ll test it myself this evening. :)


I am sorry, I figured it out using my library for character LCD module and displaying rq->wValue.word in binary using something like that.
for(unsigned char i=0;i<16;i++)

My problem is not in the transfer protocol but elsewhere…
Maybe somebody had the same problem and find some help in that comment, so again: Both V-USB and LIBUSB are working well!


Thanks for such a speedy reply :-) I figured it out, the problem was in my other function using that values….



BTW: I am using ATmega8 and woking well :-)




But anyway, I wonder why in the specification of USB2.0 you citated in the part 2 the bRequest is 16bit long and in V-USB it is 8bit long.. but i doesn’t matter for me, I’d like just to ask if there is a possibility to make bRequest be 16bit long in V-USB. Is it a modification of the protocol?


Good to hear that the tutorial code is working, also on ATmega8!!!

At least my USB 2.0 spec page 248 says bRequest is 1 byte, and wValue, wIndex are 2 bytes. The first byte at offset 0 seems to be bmRequestType. So V-USB seems to be correct. :)


Good afternoon,
Please could you publish here how to make the transfer of data in the other direction using V-USB and libusb? (Attiny to PC) I’ve read some passages from the USB2.0 specifications but I don’t grasp the practical use of the stuff… :-(
If you are busy, please give me some good source and I will try my best.. :-)

Greetings from the Czech Republic


I’m planning of doing the 4th part of the tutorial this weekend with the exact content for buffered transfers from and to ATTiny.

If you’re impatient, basically you only need to change ATtiny side usbFunctionSetup and V-USB will do the rest, you should be able to read “Hi!” from PC side buffer and nBytes should be 4 after this:

static uchar message[4] = “Hi!”;
usbMsgPtr = message;
return 4;

The LED on/off messages are already of type device->host, the part 3 example code was just currently returning zero-sized response. Additional code example can be found from V-USB custom device example (firmware side main.c). Once you understand this you can probably figure how to return a bit longer or shorter responses or no response at all (return 0) in your function. There’s a limit on how long the response can be, I don’t remember it but you can find it in V-USB docs (and my upcoming part 4).


Thank you very much for your advice, I’ll give it a try.

Looking forward to the 4th part. :-)


Thank you Jokkebk very much for the tutorial… I will work with hardware on this weekend and will let you know the feedback.And firmware code is compiling in AVR Studio 4.

Also please let me know why we are using the below mentioned functions.
usbInit(); and usbPoll();
As of now i commented on the AVR Studio for the compilation.

Jobin Jose


Jobin :
Thank you Jokkebk for the tutorial… I will work with hardware on this weekend and will let you know the feedback.And firmware code is compiling in AVR Studio 4.
Also please let me know why you are using the below mentioned functions.
usbInit(); and usbPoll();
As of now i commented on the AVR Studio for the compilation.
Jobin Jose


Thanks :-)


The usbInit() function intializes the V-USB library and is needed for it to function. usbPoll() is also part of V-USB and it does all the heavy work for us – checks if there is data to be received over USB and calls our usbFunctionSetup with all the data prepared. usbPoll needs to be called quite frequently (V-USB documentation had the exact requirements), otherwise USB functionality just won’t work.


Thanks Jokkebk … So i will add those two from V- USB. Thanks lot .. will post you the updates. For PC to communicate i want to use Lab View. Will share once it is up …


V-USB is very intuitive to use, highly recommeded. There is bit of learning curve, once passed possibilities are endless.

I did an example project a while back that includes SHT-11 sensor, if anyone interested:


Your project looks nice! Although I don’t know what that sensor does. :)

Phillipp Stengel:

hope anybody can help me. I’ve got the newest version of the CrossPack for Mac installed. And I thaught this would be a good base for compiling the usbtool of VUSB. But I’m just getting errors and warning this way:
gcc -o usbtool opendevice.o usbtool.o
Undefined symbols for architecture x86_64:
“_usb_get_string_simple”, referenced from:
_usbGetStringAscii in opendevice.o
“_usb_control_msg”, referenced from:
_usbGetStringAscii in opendevice.o
_main in usbtool.o
“_usb_find_busses”, referenced from:
_usbOpenDevice in opendevice.o
“_usb_find_devices”, referenced from:
_usbOpenDevice in opendevice.o

I tried to set the target system to 32bit but even if I do this the error is there and I’m told symbolic links for the chosen system are missing.


Thank you for this very good tutorial :) :) :)
Thank you very much


@Phillipp Stengel

It sounds like you’re missing the USB library file containing the said functions. Also, if CrossPack for Mac is the AVR development environment, you naturally cannot compile any PC/Mac side software, you need the normal gcc environment for Mac for that (and something like libusb for mac). I don’t have a Mac so cannot help you further than that, sorry. :) It seems the “standard” libusb does support Mac so compiling with it should be straightforward:


After i managed to get the rest workin, i have a problem with the host software. When i start the programm compiled with your make and usbtest.c the consol dissapeares directly. But with a bit testing i found out that argc < 2 when i start the Programm, and beacause of the exit(1); it dissapeares. Any idea where i go wrong?

But thanks for this great tutorial!


It’s a command-line tool so you need to pass it at least 1 argument – just double-clicking the icon will very briefly run the program (which will display usage, but too fast to see :). So fire up the command-line prompt and try “usbtest on” and “usbtest off” to see if LED lights.

If you have passed command-line arguments and it still exits, there’s a problem with the compiler…



Big thanks now it works ;D


thanks for the great tutorial.. I am getting the error in avr studio 4

make: *** No rule to make target `usbtest.c’, needed by `usbtest.exe’. Stop.
Build failed with 1 errors and 0 warnings…

please suggest


You should have these lines in your Makefile:

CMDLINE = usbtest.exe

$(CMDLINE): usbtest.c
gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb

Note that the gcc used here is actual PC compiler, I’m using MinGW myself. AVR Studio may not understand that and therefore fail. You can also use the above gcc command to compile it manually. Also make sure you unzipped the usbtest.c to your project folder!

Also, the project zip contains a precompiled usbtest.exe so you could just use that and maybe remove the above files from AVR Studio’s Makefile if they offend it. :)

Manash Pratim Das:


Sir please can you give the pc side communication code for using in Visual C# or Visual C++.. please your immediate help is required.

Thanks in advance.



I would assume that usbtest.c would compile just fine with Visual C# / C++ as long as you add libusb-win32 to your project – based on a quick Google search people have successfully used libusb in Visual C and C#. However, I cannot help you on the details, as I don’t have either installed and I’ve last used them several years ago.

Update: Oh and also note that the next part of this tutorial contains full source code zip, although you probably need the full libusb-win32 package to get Visual C++ -compatible library dll files.


First…great tutorial; very well written and executed–thank you.

I have another V-USB (Attiny 85) project connected to the a PC using the same vendor/device ID successfully running the lib-usb driver. I’m unable to get this project device beyond the ‘unknown device’ error on a 64-bit Win7 machine. I have tried all your suggestions above to no avail–including disconnecting the attiny 85 device.

Have you been able to connect multiple v-usb based projects (same vendor/device ID) on the same machine? Would the same vendor/device ID cause a conflict?

Thank you.


Hi Chris,
I think Windows chooses the driver based on vendor & device ID, so if you have multiple drivers for the same combo, that will cause problems (it did with me). If you’re tinkering at home you could probably just choose any device ID for the second project to avoid conflicts…



Thank you for the response. I tried changing the vendor & device ID, but had the same issue. I suspect I have a hardware issue. I’m running the 2313 at 16Mhz (only one I had on hand) and made the adjustments to the v-usb config file accordingly. I might have to match a different value capacitor (I used 15pf) on the oscillator. Wish I had a good oscilloscope or DSP to track this problem down :)


@Chris: I had a similar problem and it turned out V-USB driver files did not recompile after changing usbconfig.h so it had old settings for pins and frequency. :) Only thing that springs to my mind would be to try to find a “virgin” computer to plug your device into, to see if Windows has messed up your drivers somehow in the dev computer (there are tools and commands to purge windows usb driver cache if that’s the case).

Hope you get it fixed. And if you’re looking for an oscilloscope, check out my Picoscope review – or buy a BitScope and tell me if it’s worth it. ;)



In fact I have read your well-written review and have a Picoscope on my wishlist! I’m frozen in inaction for fear of committing $200-$300 and then regretting the purchase. A few more problems like this and I’m sure I’ll go over the edge and make the purchase. :)

I also read your problems with the changing usbconfig.h file, so I forced a clean re-compile as well as trying a different machine. That is why I suspect a hardware issue. One issue I noticed you address in the Attiny85 project is long leads…I’ll correct my wiring tonight and try again.

I’m eager to correct the problem; I have finished a LCD library for the 2313 and the usb piece is the only thing remaining. Thanks again for responding.


Success…shorter leads on the D- and D+ lines made the difference.


thanks for the good tutorial. Just to let you know: I’ve a Mac running Mac OS X 10.7 and MacPorts. I needed to install the old libusb port called libusb-legacy (the new libusb-API 1.0 does not work with the sample code). I just had to change the build target for the command line tool in the Makefile and all compiled fine:

# One-liner to compile the command-line client from usbtest.c
$(CMDLINE): usbtest.c
gcc -I /opt/local/include/libusb-legacy -L /opt/local/lib/libusb-legacy -O -Wall usbtest.c -o usbtest -lusb-legacy

Best regards,


Dominik: Thank you for the info! The new libusb interface would probably need some code changes to make it work.


what are the functions included in the header file # include


I’m sorry, it seems WordPress thought your <library.h> was a tag, could you please repeat?


buen tutorial pero tengo un problema amigo al compilar en avrstudio me sale este error

avr-gcc: usbdrv.o: No such file or directory
make: *** [led.elf] Error 1
Build failed with 1 errors and 0 warnings…

y porcierto estoy usando un atmega8 que debo hacer


Parece que el usbdrv.c no se ha compilado. Es necesario añadir usbdrv / usbdrv.c, usbdrv / usbdrvasm.S y posiblemente usbdrv / oddebug.c en su proyecto.

Otra alternativa es utilizar WinAVR para compilar el proyecto, sólo tiene que utilizar “make” en el directorio del proyecto y que se compilará y parpadeará para usted. Fusibles todavía tienen que ser cambiado manualmente.

Lo siento por mi español, estoy usando Google Translate. ;)


gracias, por el aporte !FUNCIONA PARA WINDOWS 7 64 BITS!
ya inclui los archivos que me dijiste pero ahora me salio otro error al compilarlo
que es este:

../usbdrvasm.S:391:9: error: #error “USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!”
make: *** [usbdrvasm.o] Error 1
Build failed with 1 errors and 2 warnings…

ya que quiero realizar tu proyecto para poder transmitir datos de la pc a la USART del micro y recibirlos de la misma, a y no se programar en lenguaje en C solo se programar en lenguaje ensamblador
espero de antemano que me puedas ayudar, por favor.


Suena como USB_CFG_CLOCK_KHZ no se ha definido en usbconfig.h a uno de los valores admitidos. Usted debe definir F_CPU de velocidad de reloj en Hz o establecer USB_CFG_CLOCK_KHZ a 12000, 15000, 16000 o 20000, dependiendo de su velocidad de reloj.

Alternativamente, puede ser que usbconfig.h tiene que ser en el mismo directorio como archivos usbdrv – o bien copiarlo a la carpeta usbdrv o mover los archivos de usbdrv al mismo directorio que main.c.

That’s about as far as I can help you – in case you need additional instructions, I’d suggest posting your question to a suitable electronics forum!

Ketan Kothari:

Awesome Tutorial for USB+Atmega………


thanhks for your tutorial.
but when i do the same i get this error in avrstudio:
G:\project dien tu\rf switch\AVR STUDIO\tiny2313_usb\default/../tiny2313_usb.c:18: undefined reference to `usbInit’
G:\project dien tu\rf switch\AVR STUDIO\tiny2313_usb\default/../tiny2313_usb.c:28: undefined reference to `usbPoll’
can you help me.


#include “usbdrv.h”
#define F_CPU 12000000L
#include “oddebug.h”
USB_PUBLIC unsigned char usbFunctionSetup(unsigned char data[8]){
return 0;

int main()
unsigned char i;
for(i=0; i<250;i++){
return 0;


Build started 15.4.2011 at 09:58:54
avr-gcc -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT tiny2313_usb.o -MF dep/tiny2313_usb.o.d -c ../tiny2313_usb.c
avr-gcc -mmcu=attiny2313 -Wl, tiny2313_usb.o -o tiny2313_usb.elf
tiny2313_usb.o: In function `main':
G:\project dien tu\rf switch\AVR STUDIO\tiny2313_usb\default/../tiny2313_usb.c:18: undefined reference to `usbInit'
G:\project dien tu\rf switch\AVR STUDIO\tiny2313_usb\default/../tiny2313_usb.c:28: undefined reference to `usbPoll'
make: *** [tiny2313_usb.elf] Error 1
Build failed with 2 errors and 0 warnings…


Thanks bro!

It’s work very well!!!!!!!!!!!!!!!!! :D


Testing in C-AVR Eclipse + gcc in Ubuntu 10.04


may you help me
my english is very poor
so when i do this project is ok for all above, but i dont know where the testusb.c can run. visual c++ or what.?


Easiest way is to install MinGW, it comes with GNU C Compiler (“gcc”) and GNU Make (“make”) commands which you can use to compile testusb.c. Visual C++ might also work, but the MinGW way is a lot easier.


add usbdrvasm.asm and link it .. and also add usbdrvasm.S to the source file to link it succefully the assembly level codes are contained


i am using WinAvr 4
i have tried a lot. but the problem,
undefined reference to “usbinit” …….stays
if i add the file #include “usbdrv.c”, then the problem change to linking the file usbdrvasm.
can anybody please tell me how to link usbdrvasm.S in WinAvr.


You should never #include any .c file, only header files. The C files are supposed to be compiled into separate .o files and linked together after that. The same goes with .S assembler files – first compiled into .o file and then linked.

In AVR Studio, find the “Solution explorer” from right hand side panels, right-click your project and select “Add.. Existing item” to add those two files. You may also need to add usbdrv directory as include directory for both C compiler and Assembler. And of course the project needs to be a GNU C project.

I also added F_CPU=16500000 to the defines (-D options) for C and Assembler in the project settings, and got it to compile. Hope you’ll have success!


thanks for the great tutorial.
Im using avr studio 5.1 and atmega16. I do your tutorial but dont work. I dont have error messages. But when i run the INF-wizard my device is not visible who is visible is unknown device.
Can you help me?


Sorry, I cannot help you much; only suggestions I have are to double-check connections and that USB lines are connected to the correct pins, and maybe make sure that your ATmega is definitely running at the MHz number you have specified in usbconfig.h (e.g. 12 MHz if you have 12000 kHz in V-USB config).

As an additional tip, if electrical connections are correct, Windows should play the “bell sound” when device is connected, even if the firmware has some issues. If you don’t get that, it’s likely some connector / pullup / etc. issue.


thanks for this great tutorial!!!
why not?
switch(rq->bRequest) { // custom command is in the bRequest field
case USB_LED_ON:
PORTB |= 1; // turn LED on
return 0;
PORTB &= ~1; // turn LED off
return 0;


in basic



:) Surely one could also do “PORTB ^= 1;” to just toggle the LED. I thought that the ON/OFF commands would be a bit clearer so I went with those.


This is a very nice Tutorial!

However, my host test program (Win7, VS C++ Express 2010, linking msvc\libusb.lib) does not find any USB devices although I have at least 2 devices connected: in function usbOpenDevice the call to usb_get_busses() returns only one bus with bus->dirname = “bus-0” and bus->devices being empty.

Any idea what I can do?

Many thanks in advance!


Weird. I cannot help you much. It is possible that USB devices that are keyboards, mice and mass storage would not show in the iteration. You might try to compile with MinGW’s gcc to see if that would produce a different result, or check if there’s a newer version of libusb available or something.


Stupid me. I first tried without my test board connected to the USB slot. When connected my ATtiny-USB device does indeed show up even though other devices seem not to show up (mouse, webcam, and so on). But for what I want everything works fine. Thanks for the quick reply!


Very very good tutorial,

My device had recognized by windows but I couldnt make the usbtes.c make it run, what should it promp??…when I could run it, shows:
usbtext.exe on
usbtext.exe off
usbtext.exe out
usbtext.exe write
usbtext.exe in
and then says press enter to exit..something like that
Hope you can help me.

Many thanks


Slightly belated reply, sorry for that. :) The program doesn’t prompt anything when you run it, you need to provide the on/off/etc as part of command invocation. If you just double-click the .exe, it runs the command without any parameters, which then just shows the different command-line options available.

So, you need to go to command line (Run->cmd.exe) and navigate to the directory with usbtest.exe, and type the commands “usbtest on”, “usbtest off” etc. there, or alternatively make shortcuts where you can specify the command-line options (from shortcut properties…).

Also, my tutorial part 4 has a link to a GUI version of the tool, if you prefer that. :)


hello sir
very nice easy to understand tutorial regarding VUSB. I hope you don’t mind using your tutorial as my student teaching material on microcontroller.
thank you


Thanks! And no, I definitely don’t mind, great if the tutorial gets new readers. :)

Vinod S:

This is really a great tutorial….


@Manash (26.)

Compiling with Visual C++ 20xx Express Edition

(Thanks to
Copy \libusb-win32-bin-\lib\MSVC\libusb.lib
to C:\Program Files\Microsoft Visual Studio 10.0\VC\lib\libusb.lib
Copy \libusb-win32-bin-\include\usb.h
to C:\Program Files\Microsoft Visual Studio 10.0\VC\include\usb.h
Select New -> Project -> Win32 Console Application
Name: set-led
Location: \My Documents\Visual Studio 20xx\Projects\vusb-20100715\examples\custom-class\commandline
Solution name: set-led
Console application, NO precompiled header, Finish
Select View -> solution explorer
Right click Header Files -> Add -> Existing Item -> opendevice.h
Right click Source Files -> Add -> Existing Item -> opendevice.c & set-led.c
Right click Source Files -> Add -> Existing Item -> set-led.c
Double click set-led.c
Find & Replace (Ctrl H) strcasecmp -> strcmp (4 times)
Select set-led Properties (Alt+F7):
Configuration: Active(Debug)
Platform: Active(Win32)
Configuration Properties -> Linker -> Input ->
-> Additional Dependencies, click …, add: libusb.lib -> ok -> ok
Select Build Solution (F7)

John L:

Hmm. I managed to flash the AT2313, but all I get is;

Jul 27 19:31:14 nas kernel: [267165.240854] usb 2-1.4: new full speed USB device using ehci_hcd and address 123
Jul 27 19:31:14 nas kernel: [267165.669169] usb 2-1.4: new full speed USB device using ehci_hcd and address 124
Jul 27 19:31:15 nas kernel: [267166.097377] usb 2-1.4: new full speed USB device using ehci_hcd and address 125
Jul 27 19:31:15 nas kernel: [267166.577520] usb 2-1.4: new full speed USB device using ehci_hcd and address 126

I’ve modified the code to flash an LED in the main loop, so it’s running fine. It’s just not being picked up as a USB device. I suspect I may have a problem because I am using an Arduino Uno to flash the ATTiny2313. I supply the ATTiny with 5V to flash it, then switch the PSU to regulated 3.3V to try talk USB. Anyone got any ideas what might be going wrong ?


John L:

Heh. Turns out using a 5V Arduino to try program the AtTiny while trying to read 3.3V USB data leaves you in a world of pain. I used a Fio as an ISP instead, works fine. Joy! Great tutorial!


:) Nice to hear you got it figured out! It also might’ve worked if you completely disconnect USB and 3.3V PSU while programming, and power the chip from Arduino instead.

I’ve had same types of issues when using the ISP pins for SPI communications, it disrupts the programming process…


Hi, thanks a LOT for this tutorial, I learned VUSB entirely from here. By the way, it took me 12 hours to figure out that usbInit(); was missing from my project.

Take care :)


Haha. Thanks, glad to hear that it was of use!

Akshit Maurya:

Sir,shouldn’t we be using USB_ENDPOINT_OUT instead of USB_ENDPOINT_IN in our command line client code :
if(strcmp(argv[1], “on”) == 0) {
nBytes = usb_control_msg(handle,
USB_LED_ON, 0, 0, (char *)buffer, sizeof(buffer), 5000);
} else if(strcmp(argv[1], “off”) == 0) {
nBytes = usb_control_msg(handle,
USB_LED_OFF, 0, 0, (char *)buffer, sizeof(buffer), 5000);
since we are sending descriptors from PC(host) to the device(our MCU board) as USB specification says??

Akshit Maurya:

oh!! got it we are not sending data here!!i’m such a fool to ask that question!!!


No, it’s just very confusing with the naming system, and the fact that instead of receiving data, the USB device is “sending zero bytes of data” :D


HI, I’m trying to compile the code using AVR Studio 4 and there’s a lot of error…
one of it was: ../USB.c:8:1: warning: “F_CPU” redefined, when I disabled ‘#define F_CPU 12000000L’ it disapeared.

after I added #include usbdrv.c , it still one error left: C:\AVR-Studio\USB\default/../usbdrv.c:537: undefined reference to `usbCrc16Append’ although it was defined in usbdrv.h
Can someone please help me to figure it out?


It may be that F_CPU is defined on command-line with AVR Studio, so removing the #define from code is OK.

However, you should never include .c files. Instead, add them to your project as new source files. You should also add usbdrvasm.S to your project.


Hi jokkebk!
Two Thumbs Up for your quick reply!
Thanks a lot… it all works now…
Very Good Tutorial for newbie like me :)
Waiting for next tutorial d_(^^’,)_b

Treehouse Projects:

This has been great so far! Thanks! I just can’t seem to get past a certain point, and would appreciate your help. When I try “usbtest on” or off, I keep getting “Could not find USB device!”. Any advice?


Treehouse Projects:

BTW, I changed the device name and vendor name in usbtest.c to the appropriate ones (which I defined in the INF file). So that one line in usbtest.c now reads

handle = usbOpenDevice(0x16C0, “Treehouse”, 0x05DC, “USB Test”);


Did you also change those values in usbconfig.h (vendor and device name, also lengths need to be changed)?

There are two categories of problems that could cause your error: Either the device is not recognized at all (you should hear Windows “plim” sound when you plug it in), or then there’s some problem with the usbOpenDevice parameters.

For the latter problem, you can add simple printout commands to the “search loop” in usbOpenDevice to print out all the devices, and see if your device is present, but just doesn’t match the expected vendor/device codes/names. For the former, there are a lot of HW issues that have been covered in previous comments.

Treehouse Projects:

Rock on dude! Thanks for that awesome and super fast reply! I didn’t have the correct values in usbconfig.h. Perfect, now I have everything working.

The real challenge now begins: to understand everything, and make this do something creative and useful.

Thanks again. BTW, I read your interview, and found it very inspiring. Keep up the great work!


Great to hear that you got it working!

Hope you’ll think up a nice project. I think interfacing anything between PC and something a MCU does well is fun. A couple ideas I’ve been tossing around myself:

Wii nunchuck to USB mouse “adapter”
UART to USB keyboard “bridge”


VERY GOOD TUTORIAL!! IT work very well!!!

I’M do it on **** AVRstudio 5.1 and Visual C++ 2010 ******


[details edited out by jokkebk, as it was very long and WordPress had already lost parts of code copied]



WHEN I build , it display : 1 error, 0 warning

# error “USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!”

I’check program very carefully , MY F_CPU=12000000 and very correctly?!!!
but it still display error?????

I SOLVE PROBLEM follow way:

/******* CODE IN… usbdrvasm.S ********/

# elif USB_CFG_CLOCK_KHZ == 20000

# include “”

# else

# include “” /*error “USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!” */

# endif

#endif /* USB_CFG_CHECK_CRC */

Very happy ! it don’t display error any more!
so problem has been solved!

VISUAL C++ 2010 ( Thanks to erko!)

Path of project: C:\Documents and Settings\Administrator\My Documents\Visual Studio 2010\Projects\usbtest\usbtest

project folder : usbtest
subfolder : usbtest

Copy \libusb-win32-bin-\lib\MSVC\libusb.lib
to project subfolder “usbtest” (rename “libusb.lib” to “usb.lib”, i think don’t need ,but i do it)

Copy \libusb-win32-bin-\include\usb.h
to project subfolder “usbtest”

Select New -> Project -> Win32 Console Application
name: usbtest


for(i = 0; i<250; i++) { // wait 500 ms
wdt_reset(); // keep the watchdog happy

sei(); // Enable interrupts after re-enumeration

while(1) {
wdt_reset(); // keep the watchdog happy

return 0;



WHEN I build , it display : 1 error, 0 warning

# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"

pradeep kumar:

I have gone through your is very much helpful.i have one problem that i could not generate hex file with your makefile i have changed the path in the make file but i cant. i am using avrstudio5


resume your folder project is:
C:\Documents and Settings\Administrator\My Documents\AVRStudio 5.1\AVRGCC1\AVRGCC1

so your HEX file lay in “Debug” folder follow the path:
C:\Documents and Settings\Administrator\My Documents\AVRStudio 5.1\AVRGCC1\AVRGCC1\Debug
I work on AVRSTUDIO 5, WINDOW SP. For me it like it!


Hey nice Tutorial
But I am Building ur code in MacOs X and not able to compile usbtest.c using libUSB has u mentioned Please help I am stuck now!!!!


Unfortunately I don’t have a OS X dev machine available and cannot help you with that. I’m not sure if libusb I included works with Mac OS, you might want to google around or ask some forums. Here’s one Stack Overflow article I found when searching:


Great to hear you got it working!

I removed the parts of code you got working, as the code pasted was quite long and I _think_ the Visual Studio details are already in the comments of this part or other parts of the tutorial. Sorry for that! However, I left your modification to fix the 20 MHz clock frequency setting, thanks for that!


Sir..after a lot of struggle i was able to compile the code in AVRstudio 4.
now i get the project.hex to be 16 KB
(source files that i added were-main.c usbdrv.c,odddebug.c and usbdrvasm.c)
Please tell me how to run make so as to get the main.hex file within 2 kB size.please sir.


I figured out to Make the Main.Hex file…but the size of that dot hex file is 16KB..but the maximum flash memory in ATtiny 2313 is 2 what should be done to burn this hex file into the controller,or else is it something like while burning the hex file it gets compressed and comes within 2 KB??


The .hex file is ASCII, and the actual size when flashed to MCU (in binary) will be smaller. There’s a utility to check how big it actually is, but I don’t recall the correct incantations (googling “avr check hex size” or something like that will probably give that info).

If you’re using the Makefile I provided, the .hex should fit into space of the MCU used in the tutorial. You can just try flashing it and see if it works. If you’ve made changes, it could be that 2k is no longer enough – I recall some of the later things I’ve done needed more than 2k, so I needed to use ATmega88 for those projects.

Also, adding -OS to compiler flags to optimize everything for size is a good idea, -O2 and other speed optimizations result in many cases in larger binary.


Thanks a lot..:)…by the way would u be kind enough to give us a tutorial on command line-client programming in Visual C and also about how to compile using am a newbie learning AVR on my own..its very difficult for me to pursue based on the hints that u had mentioned here..A tutorial on Command line programming part in VC and compiling using mingw would be appreciated..:)..Thanks a ton once again for this awesome tutorial..:)


I don’t know anything about VC command line capabilities, but you’re right, it might be useful to write at least a short post about command-line compiling. You can learn a bit just by looking what commands are run when you run “make” (it shows the commands as well as output), but I don’t know if there are any beginner tutorials on the topic.

I myself learned that stuff about 15 years ago on DOS so I’ve completely forgotten about the learning curve associated with command line. :)


I am getting this “new device is not recognized” notification again and again…even after trying out all the trail and error methods like plugging the usb in different ports even in different hubs as u mentioned here..still then am getting the same error message….is there a way to solve this.???..what would have gone wrong??..please suggest me..:)..Thankyou


Hmm, “device not recognized” has usually been either a configuration problem (wrong settings in usbconfig.h), or indication of some electronic issue – too heavy zeners, solder problem, wrong connection or resistor value. If you’re using my code directly, and installed the drivers, I’d wager some kind of HW problem, but it’s hard to say as the USB error messages in Windows are generally of very little help.


I’m trying to program my atmega8 to communicate with the pc via usb
i am currently done with the hardware requirements but while compiling the main.c in linux i’m getting the following error.
“make: *** No rule to make target `usbdrv/usbconfig.h’, needed by `usbdrv/usbdrv.o’. Stop.”
could you please tell me what is going wrong?


Make gives that error if there are missing files. The easiest way is to grab the full project zip from Part 4 and use that, so you’ll get all the files.

Props for using make instead of trying with AVR Studio and then being the Nth person here to ask why #include <usbdrv/usbdrv.c> does not work! :D


Hi, I have problems compiling it using provided make file. Compiler says: “process_begin: CreateProcess(NULL, gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb, …) failed.
make (e=2): The system cannot find the file specified.
make: *** [usbtest.exe] Error 2”

Would you be able to help me with that?


This is really a great tutorial, but i can’t finish part3…

When i use INF and choose “Install now”, it say “Resource already exists” but the device still cant work.

Can you give me some suggestions?

Thanks a lot><


This tutorial is so great that it enabled me to create an 8/16 bit UV-EPROM programmer with just basic C programming skills, some AVR I/O knowledge and no idea about the USB protocol. Actually it’s the first project I’ve ever done with a microcontroller.
The thing works flawlessly, but there’s a thing I’m not sure about. To program a location in the EPROM, the device must generate 100us programming pulses and I use _delay_us(100) to time the pulses. But there are interrupts occurring all the time, so I think the delays are being extended by an unkown amount. What can I do to get a precise 100us delay? Can I disable the interrupts before and re-enable them after calling the delay function?
Thanks for your time.


Have you considered using interrupts for the 100 us delays instead? As you said, interrupts get priority over normal code, and using a timer to generate an interrupt every 100 us would be rather easy.

Disabling interrupts for 100 us at time may not be a good idea (might work of course) – if your code takes 0.1 us time to do it’s work, you’ll essentially block interrupts for 99.9 % of the time – not good!


Sounds like you have some files missing, or maybe are running stuff in wrong directory. Goes “gcc” command work from command-line? Do you have libusb subdir and usbtest.c files available? I could imagine such an error for example if you don’t have MinGW (PC version of gcc, not the AVR version) installed.


Hi every one..
This is really a great and nice tutorial..thanks

I need help in some general questions..

1) Is the VENDOR_ID important when I want to devlope the V-USB Code.If yes,how can I get It?

2)Is that ID have an effect to cause an error “device not recognized”?


I have a modified code without the other files(, I download the rest files from your USB tutorial..I change the usbconfig.h ( #define USB_CFG_IOPORTNAME D#define USB_CFG_DMINUS_BIT 4#define USB_CFG_DPLUS_BIT 2#define USB_CFG_CLOCK_KHZ 12000 )and also I change the lengthe(USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 95)
the I get is “device not recognized”

What should I change to solve this problem?


1) VENDOR_ID and DEVICE_ID identify the device and Windows uses them also to find drivers for the device. If you only use your device by yourself, only thing you need to take care of is that you don’t have several devices connected to your PC with identical vendor/device ID which would need different drivers. There’s also a serial number, you can read more about all of this in V-USB documentation and USB spec.

If you want to develop a device and give/sell it to other users, you’ll need at least your own device ID. V-USB commercial licenses include your own device ID. Ff I recall correctly. Getting a vendor ID means registering to USB consortium or something and costs several thousands of dollars. If you’re considering that, you probably want to ask more somewhere else. ;)

2) Almost everything can cause the mentioned error: Bad solder joints, bad parts, wrong connections, invalid firmware, wrong fuse settings. I cannot help you much there, but I suggest you to read previous comments, I’ve had about 20-30 questions already here and other parts of this tutorial, as well as the USB password generator, those earlier questions might prove useful and contain possible answers.


Note that by default the D+ line needs to be connected to the pin that has INT0 in it, otherwise it will not work without additional configuration (see V-USB documentation if you want to find out details). Also, if you change descriptor length, be sure that you have also changed the descriptor itself. Otherwise, I cannot help you much – one way to debug it is to replicate the tutorial exactly first, then start changing things one by one, and see at which point it stops working.

In any case, “device not recognized” is already better than nothing at all – I think it means the electrical characteristics of D+ and D- lines are about OK, so pullup is correct etc. Not 100 % sure of course, ever.


I’m very happy for your replay(^_^) and hope you can help me ,,,
I change the D+ line to connect with PD4 which is INT0 and the D- to connect with PD2 ,These configration for ATmega16..
And I change the lenght to be same with the that code.

My problem is that I can’t get 3.3v for data lines and can not adjust it, I connect variable resister to play with the voltage but the voltage was not changed..
I Use resistors, zener diodes to convert 5V logic to 3.3V which is the v-usb connection..

I’m stuck now and don’t have much time because the submit deadline for the projects is very close

So please can I contact you by email so I can send you my circuit ..My Email is (


I am using the ATMEL Studio 6.0 IDE. When I try and compile things it insists that I change any “PROGMEM char” to “PROGMEM const” in usbdrv.h (e.g. line 455-const usbDescriptorDevice[]). If I make the changes to const, I get things to compile. However when I program the ATtiny85 and connect to the PC, I get a “device not recognized. I enabled the clock output just to see if things were working, and it does go through the osccal and the clock is at 16.5 MHz.

Do you think the changed from “char” to “const” should cause a problem? Do you have any simple suggestions on how to begin debugging from here? With all the timing related things going on over the USB, I am not sure how to go about debugging.

Thanks for a great tutorial!


C Brosseau:

I got these errors:

$ make

avr-gcc -Wall -Os -Iusbdrv -mmcu=atmega16 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o
In file included from usbdrv/usbdrv.c:12:0:
usbdrv/usbdrv.h:455:6: error: variable ‘usbDescriptorDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:461:6: error: variable ‘usbDescriptorConfiguration’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:467:6: error: variable ‘usbDescriptorHidReport’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:473:6: error: variable ‘usbDescriptorString0’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:479:5: error: variable ‘usbDescriptorStringVendor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:485:5: error: variable ‘usbDescriptorStringDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.h:491:5: error: variable ‘usbDescriptorStringSerialNumber’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.c:70:14: error: variable ‘usbDescriptorString0’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.c:80:14: error: variable ‘usbDescriptorStringVendor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.c:89:14: error: variable ‘usbDescriptorStringDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.c:111:14: error: variable ‘usbDescriptorDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
usbdrv/usbdrv.c:142:14: error: variable ‘usbDescriptorConfiguration’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’
make: *** [usbdrv/usbdrv.o] Erreur 1

The problem seems due to compiler’s new version. Found solution there

Solution: define variable as ‘const’ everywhere the compiler complains. You’ll have to adjust usbdrv.h and usbdrv.c files.


As noted by the commenter below, that change should make it work (haven’t tried myself on ATMEL Studio 6 though) – const is basically just an unchanging char type. Sounds like a classic USB issue, the problem likely being something in the wiring, components or connector. (usually people figure it out eventually, and the problem seems to be different most of the time)


thanks…my problem too. it compiles now. no errors, but lots of warnings. i’m using avrdude 5.11.1 on (puppy) linux 5.2.


I’m using avrdude 5.11.1 (running puppy linux 5.2). Let me state up front I am not
expecting anyone to pour over this issue. If you haven’t the time, trust me, I understand.


This is really a great tutorial, but i can’t finish part3…

When i use INF and choose “Install now”, it say “Resource already exists” but the device still cant work.

Can you give me some suggestions?

Thanks a lot><


PLeassssssssssseeeeeeeeeeeeee help me out…. :(
actually i am new to avrstudio but some how i managed cover part2 and proceed to part3,here are my problems-
1. what does it mean by project folder,i think its the folder named “default” somewhere in directories made by avrstudio. so much struggle i was able to compile and build the project, but then I hanged at this para of your tutorial- “Now let’s see if we can get it all to compile. The easiest way is to use my ready-made Makefile which also contains the necessary statements for our PC side command-line client. Put the makefile to your project folder and run make main.hex to see if it works. This way, you also see the actual commands the Makefile is used to run – there is nothing special with V-USB, the main things you need to remember is to have -Iusbdrv in place for the compiler to find the .h files from usbdrv folder, and then just having the three additional object files (usbdrv.o, oddebug.o, usbdrvasm.o) put into the same .elf file along with main.o.” what is this ‘make main.exe’ and where to i paste your ‘makefile’
3.When i use INF and choose “Install now”, it say “Resource already exists” but the device still cant work.

plz help me i don’t have any other resources to solve my problem.plz plz plz i have given my three whole days on it.


Thanks for great tutorial.
I have problem recognising avr device via USB

[ 5403.024398] hub 4-0:1.0: unable to enumerate USB device on port 1
[ 5417.628390] usb 4-1: new low-speed USB device number 91 using ohci_hcd
[ 5417.768166] usb 4-1: device descriptor read/64, error -62
[ 5418.012389] usb 4-1: device descriptor read/64, error -62
[ 5418.252176] usb 4-1: new low-speed USB device number 92 using ohci_hcd

I have used exact files from your tutorial.
I am running:
Linux 3.2.0-20-generic #33-Ubuntu

Thanks all for help


Sorry for a late reply… Regarding driver problem, I believe in most cases the drivers get installed without issue, but there’s some hardware or firmware issue with the device (bad contacts, etc.). You could try one of my USB HID examples (keyboard, password generator, etc.) as they don’t need drivers and are so easier to debug.

There are some instructions regarding the use of AVR Studio (project is just something you can create in studio), but you could also consider installing WinAVR and running “make” on the command line if you have trouble with AVR Studio (“make” is actually a utility that runs all the necessary commands to compile the program for you, so you shouldn’t need much more experience with command line than just using “cd” to get into the correct directory…

Actually, I just might make a short tutorial on command line – that would probably help me to answer those questions.


Sorry, not much I can do to help, as I haven’t tried this on Linux and don’t know if you need some drivers or not there… If you have a Win box you can try if that works better, if not it’s most likely some hardware issue with the project and not Linux-specific.


i am stuck at the “make flash” command.

when try to run make i get this error:

avrdude -p m328p -c arduino -v -U flash:w:main.hex
process_begin: CreateProcess(NULL, avrdude -p m328p -c arduino -v -U flash:w:mai
n.hex, …) failed.
make (e=2): The system cannot find the file specified.
make: *** [flash] Error 2


Sorry for not responding earlier, I did briefly look into your problem when you sent it, but couldn’t think of anything quickly and marked it for later reply… which got a bit delayed. :( Did you manage to find anything of help? Based on your lsusb output it kinda seems the device is recognized on some level, maybe version conflict between avr-gcc and V-USB causes the library not to function properly? You might also try 3V6 zeners instead of 3V3, that is what I’ve usually used.

Also, you might want to check usbconfig.h to see what device ID it’s supposed to show, if that is the same that’s shown in lsusb, otherwise it could just be that half-functioning USB device causes your ISP programmer to reassign itself and show as double..


I think it means that you don’t have avrdude installed or its directory in your PATH variable – you should be able to just type “avrdude” into command line and get it to print help about its usage.

Other possibility would be that main.hex is missing for some reason (compilation failed?)


it was the PATH variable that wasn’t set.
thank you.


Hi there! I’m a beginner at microcontroller and i really want to learn about usb communication with my device and pc. But i’m stuck at -Responding to USB control messages. I’m not able to understand what is going on and how pc sends those control messages. Please help me out from that point. thank you


The PC side example comes later in “Command line client” section – it uses libusb library in main() method to send those messages to the device. V-USB handles the low-level receiving of control messages, and calls our usbFunctionSetup() function, providing the same data that was sent from PC side to the function.

So basically we have helper libraries on both sides – in AVR side V-USB does the heavy lifting for us, and we only need to implement the usbFunctionSetup, and in PC side, libusb handles sending control messages, we can just use usb_control_msg() to send them.


thank you very i got the idea about the communication. will you please elaborate the use of make file and the line-“Put the makefile to your project folder and run make main.hex too see if it works.”


I got an issue all the time:
fatal error: usbdrv.h: No such file or directory
I’m working with AVR Studio 4 and AVR GCC.

I added folder usbdrv under my project folder:
C:\Documents and Settings\My Documents\Atmel\USB_PART2
there is .aps , .c , .aws file and folder – “default”.
In this “Default” folder i pauted usbdrv folder.
Actualy i even tried it put in C:\Documents and Settings\My Documents\Atmel\USB_PART2 here too, but even then the result is the same.

Any help !?


In addition to adding .c and .S files described in the tutorial to your project, you need to add usbdrv folder to your include directories. There is likely an option for that somewhere in AVR Studio. I’m doing a short walkthrough on this in the future, too.


Great tutorials,

i have run in to the problem that when i give the “usbtest on” command the led won’t go on.

i have checked al the settings in the usbtest.c and usbconfig.h and windows “sees” the usb device i made.

is there some way to see if the “on” signal is send to the right device or if it is send at al ?


Thanks! You could add some print statements to usbtest.c to display the devices it is enumerating, and if it has found the device etc. (so you could determine if it found the right device), so you’ll get an idea how far it goes before it doesn’t work.

Also, on device side you could maybe light the LED when the device first enters the while-loop, so you can be sure everything goes at least to that point as it should.


The device itself doesn’t seem te be entering the while loop.

and i am not sure i added the right code to usbtest.c
i added “fprintf(stderr,”%s” ,devVendor);” where it gets its vendor name.


never mind, i found what the problem was.
the uptodate main.c file was saved in a different folder by atmel studio then where the makefile was…….

it is working fine now,

thank you for your help.


I still don’t get the USB_ENDPOINT_IN, USB_ENDPOINT_OUT. Could you clarify why it feels like we should be using USB_ENDPOINT_OUT as we are sending a control message from host to device, but instead using USB_ENDPOINT_IN which is described as device to host. (PS I get the code to work, just don’t understand the theory)


Figured it out, here is the answers for those that want to know. USB_ENDPOINT_IN and USB_ENDPOINT_OUT refers the data block associated with the control message. IE is the host sending a data block to the device after the control message or is the device sending a data block after the control message.

However, if the length of that data block is 0 the direction bits are ignored.


Excellent detective work! I was just going to answer yesterday that the scheme is quite confusing, but then realized I forgot the actual details from year ago. Your answer sounds like the correct one.

RS-232 has similar hard-to-figure-out terms RX/TX which are dependent on how you look at the communication. Especially for connectors, is the RX the one where device is receiving, or the computer? Confuses me every time. :D


Hi, great Tutorial, but i have a problem, maybe you could give me some advise…

For some reason the tutorial worked great (did it last month or so), and today i wanted to build my own small usb device, but i got stuck. Ubuntu didn’t find my device. So i began with your tutorial again (to the point where the Led can be turn on/off), but it is also not working. (Cant find the device). I tried different USB Ports with no luck.

Maybe you had a similar problem?


PS i checked the usbconfig, and went through the tutorial twice ;)


Weird. Sounds like something in the hardware has changed (based on number of people who have had problems I’d say it’s finicky at best), I don’t have much more ideas than triple-checking connections and maybe seeing if shorter jump wires or something might work.


Recheck your hardware again. I also made the big stupid mistake of putting the actual pin numbers (relative to the IC) in the usbconfig.h file instead of pin number relative to the port.


Hey, very nice tutorial. Please can you help me. I did everything until Command-line client, after that I don´t know what to do. I´m new on this. Thanks


You need to install MinGW compiler for Windows, then you can compile the usbtest.c that came with the project zip (I recall there are instructions in the tutorial, probably just run “make” when in project directory) – you can then run the usbtest.exe with different command line arguments to communicate with the device.



excellent set of tutorials which have helped me a lot.

One thing that I find strange though: I can get a device descriptor by just getting a pointer to the usb_device then accessing its property dev->descriptor. But if I want a string descriptor, I have to go through all this palava with usb_control_msg(). Why do they not just implement dev->stringDescriptor or something?


Probably to save memory requirements for embedded devices that don’t want to deal with strings, or due to string internationalization issues, or both. But yeah, it’s a hassle. :)



Nice job! At the command section, the compile is wrong

C:\Documents and Settings\Brian8sune\Desktop>gcc test.c
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x4e): undefined ref
erence to `usb_control_msg’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x10c): undefined re
ference to `usb_init’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x111): undefined re
ference to `usb_find_busses’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x116): undefined re
ference to `usb_find_devices’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x11b): undefined re
ference to `usb_get_busses’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x16b): undefined re
ference to `usb_open’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x179): undefined re
ference to `usb_strerror’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x1d8): undefined re
ference to `usb_strerror’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x1ff): undefined re
ference to `usb_close’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x242): undefined re
ference to `usb_strerror’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x269): undefined re
ference to `usb_close’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x2ad): undefined re
ference to `usb_close’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x404): undefined re
ference to `usb_control_msg’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x470): undefined re
ference to `usb_control_msg’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x486): undefined re
ference to `usb_strerror’
C:\DOCUME~1\BRIAN8~1\LOCALS~1\Temp\ccwITB6Z.o:test.c:(.text+0x4b1): undefined re
ference to `usb_close’

C:\Documents and Settings\Brian8sune\Desktop>


You are right, “make usbtest.exe” only works if you grab the complete project from Part 4, without the makefile you’d need:

gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb

I’ll update the tutorial text now, thanks for the tip.


GOOD! I wonder why! Finally!


From part4 i had tried the zip example and compile with the gcc in the CMD, which still remain the same!

All the errors is about usb_….


Yeah the “undefined reference” means in 99 % of cases that some library or object file is missing from compile command, it’s the compiler’s version of “You are saying that there should be a wrench somewhere here but I can’t find it!” :D


Did you include any path from the windows?


I think libusb (with -lusb) is the only thing needed, I had it in subdirectory as the command shows.


I don’t understand!

C:\Documents and Settings\Brian8sune\Desktop>gcc -I ./libusb/include -L ./libusb
/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb
c:/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../../mingw32/bin/ld.exe: cannot fin
d -lusb
collect2: ld return 1


Do you have the libusb/lib/gcc subdirectory in Desktop, and is there libusb.a in there? If you do, it may be some version conflict, don’t know how to help then, you’d maybe need to recompile or get libusb binary yourself from somewhere.


After checking, i wanna ask one crucial question, is the compile command is “gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb” or “ggc XXX.c” ???

I don’t know, i am a noob!! Which i can generate the test.exe onto the desktop, but i am not sure how!


Problem Solve!! Although i am really appreciate to your post. I think a really really important things you have miss is to compile the file with the protocol of “ggc file.c -lusb”


That is why the project zip comes with Makefile, so people with less knowledge of C compiler workings can just type “make” and commands are run for them.

However, I’m going to continue my “basics” tutorial series quite soon which should also cover using gcc / avr-gcc and basic parameters such as -l, -L, -I and -o used for this one. I’ve been coding C so long I sometimes forget not all know this stuff before starting electronics. :)


I am only an electronic engineering, which only cover the hardware software, but not computer software at all. Usually computer software is given to those developer. Different gcc compiler require different syntax, it is impossible to remember all the protocol!


I wonder how to make the GUI of the XX.exe? I am not sure about mingw, can i use visual basic to make the GUI?


When I compiled the AVR code I got an error message saying “undefined reference to `usbCrc16Append’ ” I included usbdrv.h and usbdrv.c. I found usbCrc16Append
defined in both files. Anyone know why it can’t see the definition of usbCrc16Append?

Joonas Pihlajamaa:

You should not include both, just include the .h file in source code and compile usbdrv.c separately, and have the resulting usbdrv.o in the final linking phase. If you’re using AVR Studio, you need to add V-USB .c and .S files to your project, or use the Makefile and “make” command to compile stuff from command line.


Once again many many thanks for this wonderful tutorial.

I am using

Atmega32A MCU,
16mhz clock
22pf capacitors
USBASP programmer

Windows 7, 32 bit OS and Machine!

The first part of the tutorial went smooth!

In the second part I had to face the trouble of powering the mcu from the USB rather than the programmer and faced good amount of issues. Okay no problems! I decided to program the mcu separately.

I am now in the third part of the tutorial. I copied the code and changed all the parameters according to my specs in the makefile and updated the clock speed in the main.c and compiled it. Lo it complained about the missing files and I promptly fixed it from your tutorial files. After this the usb was detected as ‘Unkown Device’. Tried generating my INF file using the inf wizard of the libusb driver package still no luck.

Guessed my code is wrong somewhere hence flashed your usb tutorial files but still the same results.

Can you tell me what could be the problem here? I would be happy to shed more light/details you would want more!




Firstly my sincere apologies to the author Joonas and every other users here due to my hills and mountains of stupidity.

Firstly, the USB worked completely fine. I will list down the errors/mistake that I committed.

* I tried compiling the program using programmers notepad. As the author has clearly instructed how to use the makefile and the make commands please adhere to it (for people like me).

* Next though the circuit was all correct and fine, there was one big issue. The D+ and D- pins were connected to the wrong places in my MCU.

* Then the device installed smoothly and got detected as USBAsp (as my programmer is USBAsp). Once you update the driver with your inf file then it will update the device name with the name you have provided in the usbconfig.h

* Finally, if you notice the usbtest.exe is not working then kindly update the device name and vendor name in the usbconfig.c, then compile it then use it for correct working.

* Rest is history.

Lessons learnt by me

* How to program or add USB support for your MCU
* Always read a tutorial thoroughly before complaining.

Finally, mY big thanks to Joonas. Where do you live Joonas? I owe you a beer and a lunch maybe! Cheers everybody.



Joonas Pihlajamaa:

Haha. Kudos to you for sharing your findings, I think there have been about two dozen people who have got stuck into “device not recognized” part, but only one or two have later updated where the failure was (wrong connections and config probably the most common reason), and none so informatively. :)

Great that you got it working, and hope you’ll have fun with USB devices in the future!


PS. I live in Finland and only drink cider, but if you want you can send a virtual beer via Donate-button on the right. :D (actually, it will most likely be spent on new ATtiny MCUs :)


Yeah I had been laughing my day off because of the fun|stupid|innocent mistakes and the USB not working and realizing it. So you are from Finland? Great! I was living in Wales, Bangor until 20 days ago for more than a year and came back to India after completing my Masters. Too sad this conversation did not happen then, else I would have gladly sent you Strongbow!!(Guess you like it). Otherwise no issues soon I will get my bank accounts settled here and will happily make a donation. You can invest it on an Atmega MCU and make a USB connection based device that will blend Ciders using Atmega and the air surrounding the device! will be a great hit in the market! :-)


I tried compiling the usbtest from my ubuntu linux box and I get this following error for the following command


make all


gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb
In file included from usbtest.c:13:0:
./libusb/include/usb.h:5:21: fatal error: windows.h: No such file or directory
compilation terminated.
make: *** [usbtest.exe] Error 1


./libusb/include/usb.h:5:21: fatal error: windows.h: No such file or directory

Any Ideas???


Step 1

First as an user with administrative rights use the below command

sudo apt-get install libusb-dev

The above steps ensures that the libusb files are installed and configured. Just use the command and rest will be taken care by itself.

Step 2

Replace the lines in the Make file with the ones as shown below

# One-liner to compile the command-line client from usbtest.c
$(CMDLINE): usbtest.c
#gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb
gcc -O -Wall usbtest.c -o usbtest.exe -lusb

Step 3

Upon completing the above two steps now you can run the program by typing any of the commands

./usbtest.exe on
./usbtest.exe off



when I plug in my usb and look at the dmesg I get as shown below

[12648.904274] usb 5-1: >new low-speed USB device number 76 using uhci_hcd
[12649.028217] usb 5-1: >device descriptor read/64, error -71
[12649.252086] usb 5-1: >device descriptor read/64, error -71
[12649.468222] usb 5-1: >new low-speed USB device number 77 using uhci_hcd
[12649.592215] usb 5-1: >device descriptor read/64, error -71

I am using Ubuntu box. Can someone throw some light on this?

Joonas Pihlajamaa:

Yeah, it’s a pain to remember. Thankfully the gcc include and library options have stayed much the same for past 20 years, otherwise I wouldn’t remember them myself either. :D

Joonas Pihlajamaa:

You can use anything that can interface with libusb, many Visual Studio -powered languages likely work, like C# and if they still have a version of VB ( around. Even MinGW can do it but you have to be more low level with that one (I just know it can be done, not details unfortunately).


First of all, thank You so much for making this tutorial! You’ve helped me a lot in getting my USB working.
I’m almost completely done except for one part:
reading/writing data.
I’m working in Visual Studion in C# and I hope you can help me solve my problem:
– I’ve downloaded your code and I’ve programmed it to my MCU (AtMega162)
– I’ve written the code and I can turn my LED on/off.
– I’m trying to get the MCU to send data to my PC but somehow I just can’t manage…
My code should be good (since the LED on/off part is working), so I’m stuck with the parameters the function needs.
What I’m using:
UsbSetupPacket Packet = new UsbSetupPacket((Byte)UsbRequestType.TypeVendor, 2, 0, 0, 16);
transferSuccess = MyUsbDevice.ControlTransfer(ref Packet, buffer, buffer.Length, out TransferredLength);
Here’s some info on the C# code:

The function returns TRUE, so the transfer should be done. The TransferredLength returns the amount of bytes correctly. Yet when I go through the buffer array, it’s unmodified! What am I doing wrong? I’ve spent hours trying to figure out what’s wrong, I’ve read many pages, googled for hours with no result. You’re my last resort!

Thank You for reading!
I’ve got much hope in this…!

Joonas Pihlajamaa:

Hi. Thanks for the compliment. I don’t know any C# so it’s hard to comment your code – but the part you showed looks perfectly OK. Only idea I had that if the buffer is properly initialized, not shared with anything else that might clear changes made by USB, and sufficiently large (I’d try something like 10-100 bytes and maybe vary the size to see if makes a difference).

Based on that, I was wondering if your firmware side code is OK. Are you using the example code I had or a modified version? You might want to try the C example first and when you’re sure the HW works, switch to C# so you can eliminate possibilities for error on the other side.

Also, take a look at for longer data streams.


Thank You for the quick reply!

Just as an additional information, I have a red LED tied to D- and a green LED tied to D+. The green usually only lights up for a few milliseconds on data transfer.

I tried varying the size of the buffer. I started off from 256 and started going down. Odd thing is that as soon as I go under 16 (note: this is the size of the static uchar replyBuf[16] = “Hello, USB!”;), the green LED lights up for several seconds (~5 sec) and then the function returns a FALSE (transfer unsuccessful).

I was wondering whether the type of my buffer is incorrect.
I tried with Byte in which case I get a bunch of 0 returned.
I tried with Char in which case I get empty chars returned.
I tried filling up the buffer with chars and then let the function modify it, but it didn’t.

I doubt there would be anything that would modify the buffer after the function did it’s little magic, since the next line of code is to loop through the buffer array and write-out the results to a textbox.

The hardware code is the un-modified (except for D+, D- and interrupt pins as well as the device name – note: I’m using AtMega162) .zip content You provided in part 4 of the tutorial.

I’ll try to paste a bit more of the code:

private void butSendRec_Click(object sender, EventArgs e)
Int32 TransferredLength;
byte[] buffer = new byte[15];
bool transferSuccess;

//find th USB device with the ID
UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(0x16C0, 0x05DC);
//open the found device and set My Device to it
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
UsbSetupPacket Packet = new UsbSetupPacket((Byte)UsbRequestType.TypeVendor, 2, 0, 0, 1024);
transferSuccess = MyUsbDevice.ControlTransfer(ref Packet, buffer, buffer.Length, out TransferredLength);

if (transferSuccess == true)
TbWrite(“data transfer complete!” + Environment.NewLine + “length recieved: ” + Convert.ToString(TransferredLength) + Environment.NewLine);

for (int i = 0; i < buffer.Length; i++)
tbMain.Text += buffer[i];

catch(Exception ex)
MessageBox.Show("Error with data tranfer!" + Environment.NewLine + ex.Message);


Thank You for Your patience! :)


I added an else if statement after the if(transferSuccess == true)

else if (transferSuccess == false)
MessageBox.Show(“error in data transfer…”);

So if the buffer array is < 16, then the error message is shown.

I'm quite sure that the code should be fine, but there's some problem with my buffer…maybe it's type. I've tried pretty much every type and I only received an error when I made the buffer a string.

What bothers me is that if you look at the libusbdotnet site for the ControlTransfer Method:

then you can see that the buffer type… IntPtr buffer.
What does that mean?

Much respect,


Sorry for writing so much, just trying to keep you updated of the things I’ve tried.
I’ve just re-flashed the original code that you wrote. Actually I didn’t even need to change the D+, D- pins. So exact same code that is provided by the .zip in part 4 is on the MCU and the reply buffer contains unchanged values.

I hope You can solve this…it would open up a whole new world for me… :) It’s like we’re picking the lock to it and we’re just half an inch away…

Joonas Pihlajamaa:

I now spent half an hour recreating the circuit, but knowing no C# it will take me quite long to rewrite the usbtest.c for C# and Visual Studio. Do you have a source file and project I could try out?

Also, did you try the circuit with my usbtest.exe built from C source, and have success with “usbtest out” and “usbtest in xyz” + “usbtest out” commands? It could be theoretically possible that the circuit is somewhat unstable, working with short commands like LED ON/OFF but failing with data transmission (although quite unlikely).

Joonas Pihlajamaa:

After two hours of learning C#, it seems the problem with your code was that you had ignored the other RequestType parameters specified in usbtest.c than the type – direction of data bit (bit 7) needs to be set when reading, and recipient for control code needs to be “device” (actually zero bit so that could be omitted).

Also, I’m not sure if additional code I wrote to transform a byte array to IntPtr was necessary, but I did it anyways. In any case, here’s a tested-working code for C# that implements LED ON/OFF and data in/out to device. I really haven’t coded C# before so the string to byte array to IntPtr and vice versa conversions are adapted straight from StackOverflow examples, a proficient C# writer might shave off a few statements:

I usually charge $40 hour for custom code, but I think I learned something valuable from this myself. Maybe I’ll try out C# more extensively in the future, now that I have Visual Studio installed. ;)



WOW! Thank You so much for the effort, time, patience and kindness!

Today during my lectures, I was thinking about the byte requestType beign the issue… it would’ve probably taken me weeks to figure this whole thing out.
I just checked, and it turns out that using a byte type buffer array works just fine.

I wish more people would be like You… :)
I would be more than happy to donate to such a kind, helpful, generous person. Frankly I’m an engineering student in Hungary and as far as I know, my student card doesn’t support online payment… :(

By the way, I’ll try and make a decent YouTube video that would sort of work like a pointer for people trying to start off projects like this, showing them where to start (HERE!), and what they need.
Also if You’re interested, I’ll keep You updated if I manage to get some projects done (like communicating with a car OBD, RGB LED controlling via PC (through an MCU), and so much more in my mind…) As I mentioned I’m an engineering student (mechanical / manufacturing), so the my biggest problem is time… :)

Ow and, I’m a happy owner of a D300 too ;)

Once more: THANK YOU SOO MUCH!!!
I just can’t wait to explore this whole new world! (So excited)

Joonas Pihlajamaa:

Thanks for the kind words. Have fun with the project!

Sean Bietz:

I’m getting an error when compiling the example code in Atmel Studio 6.1, here it is;

#error “USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!”

Any advice? Thanks.

Joonas Pihlajamaa:

Exactly what it says, the value is defined in usbconfig.h and can only be 12000, 16000, 16500, 20000 and possibly few other values. Anything else and it gives that error, as the timings won’t work for USB. Make sure you have crystal that uses a supported rate and define it in usbconfig.h.


“And of course the project needs to be a GNU C project.”
My project was set as C++, I’ve been looking so long for this solution, thank you so much, man!


i posted a link on my blog, but i was able to get your tutorial up and running on the adafruit trinket hardware :)

thanks for all your help!


Regarding the issues where Windows appears to cache outdated or incorrect USB port config info: You may be interested in this similar problem we had with Teensy, and its resolution:

Joonas Pihlajamaa:

Thanks, useful info!

Jose Ali:

I would like to know, where do you compile the main.c?

I am testing winavr. I have these undefined reference
C:\Users\p\Desktop\1/testusb.c:20: undefined reference to `usbInit’
C:\Users\p\Desktop\1/testusb.c:33: undefined reference to `usbPoll’

I don’t know what I should do


Thank You for this tutorial! I used atmega8a (3.3V) instead of ATtiny2313 and everything works fine, but now i need my PD3 (int1) to be used by another uC.

Only change I made is (usbconfig.h):
and connected 1.5k to this pin.

Im using avr-gcc (WinAVR 20100110) 4.3.3(?)

The thing is, when I make and program new code the uC still works on setting with D- on PIN 3. I can read registers and send msgs like nothing changed, yet the program in uC is new one.

Can you help me solve this problem?

Joonas Pihlajamaa:

I have a Makefile which compiles things in usbdrv folder (or what was it’s name). There’s info in previous comments about WinAVR, basically you need to add also the necessary V-USB files to the project.

Carl Reinbold:

Hello, and thanks for your help. I am trying to compile the code from part 3, and I get a compiler error saying #error “USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!”. I made sure to set F_CPU to my clockspeed of 12 mhz. when I went into usbconfig.h to enter #define USB_CFG_CLOCK_KHZ 12000, I found that the expression “F_CPU/1000” was already there. I commented it out, and entered 12000 as in your example and got a pile of “usbdrv/ Error: constant value required” errors instead. Can you please help me with any ideas about what is wrong? I am using gcc-avr on debian linux to compile. Thanks.

Joonas Pihlajamaa:

Hmm, one idea is to try define F_CPU with the -D option to the compiler, as usbconfig.h when included in usbdrv files doesn’t find it from your main.c or anything like that. Also, when compiling stuff in usbdrv, unless you are in the folder, you might need -Iusbdrv to add that file to include directories…

If you are on Debian, you might try my Makefile for compiling in the examples, if it compiles OK, you can just start tracing the differences to your project. That’s all I can think of, good luck!

Joonas Pihlajamaa:

I don’t remember which pin used also the interrupt, but for that pin, there is additional #defines to switch to using another interrupt. Also, unless you have dependencies set up, it might be the usbdrv/ files are not recompiled with correct settings, happened to me earlier. Easiest way to make sure is to delete the .o files and then recompile.


Hi.. I am ajit paul from India.. A beginner in embedded programming. First of all.. Thanks for this wonderful tutorial. I am using atmega8L IC clocked at 12Mhz with crystal. connections are made as per your diagram. PD2 is INT0 >>D+, PD3 is INT1 >>D- hence usbconfig.h is not changed, its same as attiny… I connected everything and plugged in… no response.. then when i changed “for(i = 0;i<250; i++)" to "for(i = 0;250; i++)".. (dunno wat happend) i got the windows chimes and showed USB device not recognized (Device Descriptor Failed).. Dont understand… I plugged it in another comp. but same error.. I tried manually installing the driver using INF WIZARD, but when i try installing it, it shows "Other error".. I am totally out of ideas.. thats why I am causing trouble for you..I am really sorry… Need help, I am trying this thing for around 10 days… cannot figure whats wrong.. I am using AVR Studio.. Windows 8.1, Hewlett Packard Laptop, USBasp programmer…. please help.. :(

Joonas Pihlajamaa:

Not many ideas here either, unfortunately. Having just “250” in the middle part of for-loop will cause it to run forever, because it is always non-zero and thus true. You might want to try some electronics forums if they have ideas. If the pins are the same, it would point to a hardware issue, but it could be there is some slight differences still in the hardware…


I will try some things out.. even on an attiny… let me check if anything works out !! :( thank you for your response sir… :)


Same issue…
Hardware : USB Stick from Sparkfun

Device work on WIndows 7 But in WIndows 8.1 “Unable to read Descriptor”

I’m trying to read documentation about USB Stack change in windows 8… but a lot of…. Crrapppy Headheach…


I have the same problem.Can someone please help me with this problem? Thank you in advance.

Joonas Pihlajamaa:

Hmm, maybe there is another driver already installed for the device ID? In that case uninstalling the driver might help. But could also be a Win8-related problem, as I wrote this tutorial on Win7 a few years ago.


Thanks Joonas. But I still got another serious problem. I uninstall the driver, recreate and re-install it again as you said. Everything seems fine.Then I plug the DIY passgen in and the computer keep saying “USB device not recognized”.So I decide to update driver software(in device manager) with the one I’ve just built, but the result is, “The folder you specified doesn’t contain a compatible software driver for your device. If the folder contains a driver, make sure it is designed to work with Windows for x64-based systems”. What does it mean? How can I fix it? Please help. I’m working on my university project and I stuck with this problem for 2 weeks. Please, I need help.

PS. I use Window 7 64 bit operating system.

Joonas Pihlajamaa:

There should be an installer_x64.exe in the project zip with drivers that worked at least for me on Win7 64bit. Some previous readers who have had the “device not recognized”, it has usually been a problem with the USB hardware (or fuse settings / firmware) and rarely a driver issue. The range of reasons has been from bad connections to zeners and resistors which did not work, and everything else, so hard to give any specific advice. :( Good luck in your troubleshooting!


Thank you very much Joonas. I’ll try my best.


Finally, I can get through this.All problems have been solved. The DIY password generator is working fine. In my opinion ,the reason why those problem occurred is about circuit.

1) I think it’s about wiring. I use too long wire, so I cut all the long wire as short as possible and solder it on PCB instead of breadboard.

2) I realized that the fuse value I use was wrong.My mistake.

That’s all. Thank you very much Joonas. I earned a lot of knowledge from these tutorial, especially the DIY pass gen.

PS. I try to plug the DIY passgen in different laptop to prove that it’s working fine. Unfortunately, it can work in some laptop. My first thought, I think it’s about operating system, but after I try to use the USB in Window7, I try it in Window8. It still works. Maybe my assumption is wrong.

Do you have any ideas or any suggestions about this problem? Thank you in advance.


thanks for this wonderful tutorial, Im using linux ,I made AVR USB by atmega8a everything is correct in micro and pc ,I can led off and and on but ,I have problem i can’t do this by usb cable (error : Could not find USB device!),I’m using parallel cable and it’s working!! why usb can’t.


I am new to Embedded-C world.
I have following doubts, please help me out.
1)I don’t understand what a “MAKE” file is can you please give a link for what is it and how do we make.
2)I am working with Atmel Studio 6 and included all the files in my project using “Solution Explorer” from V-USB folder but I still get the error undefined reference to “usbInit()” and “usbPoll”. Please help me out.
3)Please explain what is a .s file and I am recieving the error for Khz setting. but I already set it to 12000 still get the same error.
Thank you.


Device work on WIndows 7 But in WIndows 8.1 “Unable to read Descriptor”

Joonas Pihlajamaa:

Late reply… “make” is a command which reads “makefiles” which contain instructions how to compile and build code from sources. It comes with most GNU C Compiler suites (Windows mingw, installed on Linux as default), so once you have it, you can just go to command line and type “make” in the project folder, and it runs all the commands automatically for compiling. You can google for “gnu make” or “makefile” for additional information.

Surya Teja:

we are doing a project for implementing usb protocols in attiny2313. we started with your tutorial we have designed the hardware but while dumping the code our device is not recognized . we tried each and everything to sort out the problem but vendor id and product id is not being found even we have entered manually.Finally, we got resource is already exist. we have completely verified our hardware but didn’t found any error in hardware.


I have a problem “make: *** [Usb tiny2313.elf] Error 1 Usb tiny2313 C/C++ how can i fix it tenks

Joonas Pihlajamaa:

Doesn’t sound like the full error text. Do you have the full error?


Tutorial is based on deprecated version of libusb API :-(


Although it is great anyway :-)


This is a great tutorial.
I am following using UBUNTU until creating usbtest.exe … but
when I run
./usbtest.exe on
it responded:
Could not find USB device!
I have done plug/unplug the USB connector; had installed libusb, burn the ATtiny2313. Why this is happen?
Help please.


Nugraha, first of all check if you device is recognized – having plugged it in, launch dmesg command (in terminal). You should see something like this:
[26291.523074] usb 1-1: new low speed USB device number 2 using uhci_hcd
[26291.686018] usb 1-1: New USB device found, idVendor=16c0, idProduct=05dc
[26291.686062] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[26291.686068] usb 1-1: Product: USB_dev_name
[26291.686072] usb 1-1: Manufacturer: Your_vendor_name
In place of Product and Manufacturer you should have Product and Vendor name you have set in usbconfig.h
If device is recognized, check if Product and Manufacturer set in command-line client are the same as these in usbconfig.h


Hi slawek,
nice to meet you and thanks for your hints.
I did the following command:

… yes, now I found the device as:
Bus 003 Device 002: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb.
… and the new USB is recognized:
[ 72.400060] usb 3-1: new low-speed USB device number 2 using uhci_hcd
[ 72.572865] usb 3-1: New USB device found, idVendor=16c0, idProduct=05dc
[ 72.572869] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 72.572873] usb 3-1: Product: USBexample
[ 72.572876] usb 3-1: Manufacturer:

* I reconstruct my breadboard and then everything is OKAY and I am so glad.
Thank you.


Thank you for your explanation.
However, There are so many error in my compiler, atmel studio 6.1.
Please tell me what you use for compiling.

most of error like this
error 17 variable ‘usbDescriptorDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ C:\Users\pkang\Documents\Atmel Studio\6.1\HID_AT8\HID_AT8\usb\usbdrv.h 455 6 HID_AT8

Joonas Pihlajamaa:

I think the compiler has been updated after this tutorial, and the old version of V-USB and this tutorial will cause warnings. Upgrading V-USB to latest version might help, but I think there might be some code changes needed to tutorial code also. Unfortunately I have not compiled this in a while, so quickest help would be through Google…


If any one is getting an error about “-assembler-with-cpp” flag, change it to “-x assembler-with-cpp” in /Users/chris/Documents/Arduino/hardware/tiny/avr/platform.txt


I had some trouble using the library. It says these things as error, I am new to embedded and i know this is some atmel 6.2 issue, but how do i fix it.


Error 5 variable ‘usbDescriptorStringVendor’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 479 5 passsowrdvusb
Error 7 variable ‘usbDescriptorStringSerialNumber’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 491 5 passsowrdvusb
Error 6 variable ‘usbDescriptorStringDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 485 5 passsowrdvusb
Error 4 variable ‘usbDescriptorString0’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 473 6 passsowrdvusb
Error 3 variable ‘usbDescriptorHidReport’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 467 6 passsowrdvusb
Error 1 variable ‘usbDescriptorDevice’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 455 6 passsowrdvusb
Error 2 variable ‘usbDescriptorConfiguration’ must be const in order to be put into read-only section by means of ‘__attribute__((progmem))’ c:\users\marcell veszpremi\documents\atmel studio\6.2\passsowrdvusb\passsowrdvusb\usbdrv.h 461 6 passsowrdvusb



Thanks for this amazing tutorial. I am new to embedded world, i have just worked with atmel studio so the command line execution is a new thing to me.

I am trying to learn the compilation using command line. I have also read your tutorial completely and i know that you are not so happy that many people don’t know how to work on command line.

I needed some information:
1. To learn GCC compiling where do i start.
2. I am trying to compile the windows side usb file using gcc and libusb libs, i am using the commands you have given above:
“gcc -I ./libusb/include -L ./libusb/lib/gcc -O -Wall usbtest.c -o usbtest.exe -lusb”

But i am getting an error which says: “skipping incompatible when searching for -lusb”

I can see that i have not understood how gcc works and what all commands are available, this is the main reason i wanted to know where i can learn the gcc compiler and it’s commands as pointed out in 1. above.

Kindly help me out, waiting for your reply.
Thanks in advance.


Hi i am desperately waiting for your reply. Please help me out on the error.

Joonas Pihlajamaa:

Hi Nadig. I am sorry, I currently don’t have enough time in my hands to help on issues related to the tutorial. I suggest you try AVRfreaks forum or some other online community, if there would be people who could help.

Amanpreet Singh:

The article is really nice and easy to understand.
I successfully completed the device part.
But when I tried the command make usbtest.exe, it gave the following error:
gcc: error: CreateProcess: No such file or directory

I tried solving the problem, but its still there.
Is there anything I am missing?
Please help
Thank You

Joonas Pihlajamaa:

Sounds some kind of compiler error, you might want to google that error message and see if there’s anything that is helpful. I’m afraid I don’t have any suggestions.

Alberio Lima: is old, no compile


I had some problems getting this to work on linux (arch x86_64). Rewriting the driver-software with to comply with libusb-1.0 solved my problems however.

Fantastic tutorial!


I did this on an ATmega328P, no problem extending this tutorial to other AVR mcus.


include “usbdrv.c” to your project.
goto solution explorer panel and right click on your project. then select add>>existing item and add usbsrvasm.S to your project.


put a “const” before every definition


Final hex file is 5kb size, but ATtiny2313 having only 2kb. How u flashed the hex file.
Please help me.


Joonas Pihlajamaa:

It’s been a while since I wrote this, but V-USB library needs some space optimization compilation flags if I recall correctly (-Os to optimize for small size) at least. The .hex file is in ASCII (two characters to represent a byte plus a bit overhead in the file) so a bit over 4 kB should still fit into 2 kB of flash, so it’s close.

Sajjad Ahmad:

Sir I am a hobbyist, and wanna to make your project “Password Reading USB” but after reading some article I am not getting idea of programming Atmel ATTiny micro controller please help me which compiler you are using for it.

Sagar Lakhani:

Best tutorial.. thank you :)


I have errors:
Id returned 1 exit status
recipe for target ‘USBtiny.elf’ failed
undefined reference to ‘usbInit()’
Help please)

The Night Whisper:

Many many ……………………. THANKS SIR
Very Perfect tutorial also and the most important thing which make it Value is “It’s Working and applicable”

The Night Whisper:

By My self
I’ve build it on Win10 X64, and used MS-VS-2017 for the client program
and it working like charm