hi, anyone have libusb compilled for friendly arm linux? thanks
libusb
Well it's not so complicated. Which version you need? Always same cross-compilation. Or use buildroot to build libusb. marek
Hi! I successfully cross compiled libusb using the arm-linux toolchain... $ TOOLCHAIN=/usr/src/mini2440/arm-2008q3 $ PATH=$PATH:$TOOLCHAIN/bin $ CC='arm-none-linux-gnueabi-gcc -march=armv4t -mtune=arm920t' $ CROSS_COMPILE=arm-none-linux-gnueabi- $ export CC CROSS_COMPILE Grab a copy of the usblib source, crosscompile and install the ARM library into toolchain. $ tar xfv libusb-1.0.6.tar $ cd libusb-1.0.6 $ ./configure --host arm-linux $ make $ cd libusb $ cp libusb.h $TOOLCHAIN/arm-none-linux-gnueabi/include/c++/4.4.3/ $ cp .libs/libusb-1.0.so $TOOLCHAIN/arm-none-linux-gnueabi/lib/ but if I run a simple code like: #include <usb.h> #include <iostream> using namespace std; int main() { int NO_OF_DEVICES; int NO_OF_BUSSES; usb_bus* busses; usb_init(); cout<<"\nUsing usb.h\n"; return 0; } and compile & link it using: arm-linux-g++ filename.cpp -o executablename -lusb i get the following error: /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../../ ../arm-none-linux-gnueabi/bin/ld: cannot find -lusb collect2: ld returned 1 exit status also: if i compile and link using: $ arm-linux-g++ usb_cc.cpp -o armusb /tmp/ccDL0e1R.o: In function `main': usb_cc.cpp:(.text+0xc): undefined reference to `usb_init' collect2: ld returned 1 exit status Please help....
thanx Marek for ur prompt reply! I recompilled libusb with a prefix using: $ ./configure --host=arm-linux --prefix=/home/abhinit/libusb/install $ make $ make install after this, as u pointed out, I tried: $ arm-linux-g++ usb_cc.cpp -I /home/abhinit/libusb/install/include -o myusbprog -L /home/abhinit/libusb/install/lib but I'm still getting the following error: /tmp/cc8lo4E2.o: In function `main': usb_cc.cpp:(.text+0xc): undefined reference to `usb_init' collect2: ld returned 1 exit status I'm not able to figure out whats going wrong...
I tried this too: $arm-linux-g++ usb_cc.cpp -I /home/abhinit/libusb/install/include -o mydvr -L /home/abhinit/libusb/install/lib -lusb I got: /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../../ ../arm-none-linux-gnueabi/bin/ld: cannot find -lusb collect2: ld returned 1 exit status
I modified the program as: #include "libusb.h" #include <iostream> using namespace std; int main() { int NO_OF_DEVICES; int NO_OF_BUSSES; usb_bus* busses; usb_init(); cout<<"\nusing usb.h\n"; return 0; } and tried this: root@abhinit-laptop:/home/abhinit/Desktop# arm-linux-g++ -v usb_cc.cpp -I /home/abhinit/libusb/install/include/libusb-1.0/ -o mydvr -L /home/abhinit/libusb/install/lib/ Using built-in specs. Target: arm-none-linux-gnueabi Configured with: /opt/FriendlyARM/mini2440/build-toolschain/working/src/gcc-4.4.3/configure --build=i386-build_redhat-linux-gnu --host=i386-build_redhat-linux-gnu --target=arm-none-linux-gnueabi --prefix=/opt/FriendlyARM/toolschain/4.4.3 --with-sysroot=/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi//sys-roo t --enable-languages=c,c++ --disable-multilib --with-arch=armv4t --with-cpu=arm920t --with-tune=arm920t --with-float=soft --with-pkgversion=ctng-1.6.1 --disable-sjlj-exceptions --enable-__cxa_atexit --with-gmp=/opt/FriendlyARM/toolschain/4.4.3 --with-mpfr=/opt/FriendlyARM/toolschain/4.4.3 --with-ppl=/opt/FriendlyARM/toolschain/4.4.3 --with-cloog=/opt/FriendlyARM/toolschain/4.4.3 --with-mpc=/opt/FriendlyARM/toolschain/4.4.3 --with-local-prefix=/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi//sy s-root --disable-nls --enable-threads=posix --enable-symvers=gnu --enable-c99 --enable-long-long --enable-target-optspace Thread model: posix gcc version 4.4.3 (ctng-1.6.1) COLLECT_GCC_OPTIONS='-v' '-I' '/home/abhinit/libusb/install/include/libusb-1.0/' '-o' 'mydvr' '-L' '/home/abhinit/libusb/install/lib/' '-shared-libgcc' '-march=armv4t' '-mtune=arm920t' '-mfloat-abi=soft' /opt/FriendlyARM/toolschain/4.4.3/libexec/gcc/arm-none-linux-gnueabi/4.4.3/cc1p lus -quiet -v -I /home/abhinit/libusb/install/include/libusb-1.0/ -D_GNU_SOURCE usb_cc.cpp -quiet -dumpbase usb_cc.cpp -march=armv4t -mtune=arm920t -mfloat-abi=soft -auxbase usb_cc -version -o /tmp/cc2ErcIo.s ignoring nonexistent directory "/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi//sys-root/opt/Fri endlyARM/toolschain/4.4.3/arm-none-linux-gnueabi//sys-root/include" #include "..." search starts here: #include <...> search starts here: /home/abhinit/libusb/install/include/libusb-1.0/ /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../.. /../arm-none-linux-gnueabi/include/c++/4.4.3 /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../.. /../arm-none-linux-gnueabi/include/c++/4.4.3/arm-none-linux-gnueabi /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../.. /../arm-none-linux-gnueabi/include/c++/4.4.3/backward /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/include /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/include- fixed /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../.. /../arm-none-linux-gnueabi/include /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi//sys-root/usr/include End of search list. GNU C++ (ctng-1.6.1) version 4.4.3 (arm-none-linux-gnueabi) compiled by GNU C version 4.3.0 20080428 (Red Hat 4.3.0-8), GMP version 4.3.1, MPFR version 2.4.2-p2. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 272180abb628adcb1c40ce71992c9286 usb_cc.cpp: In function 'int main()': usb_cc.cpp:9: error: 'usb_bus' was not declared in this scope usb_cc.cpp:9: error: 'busses' was not declared in this scope usb_cc.cpp:10: error: 'usb_init' was not declared in this scope
With: #include<libusb.h> I can see my path included as: . .. #include <...> search starts here: /home/abhinit/libusb/install/include/libusb-1.0 /opt/FriendlyARM/toolschain/4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3/../../.. /../arm-none-linux-gnueabi/include/c++/4.4.3 . .. but the program still won't link...
Have same. I modify your code to: #include <libusb.h> #include <iostream> using namespace std; int main() { int NO_OF_DEVICES; int NO_OF_BUSSES; //usb_bus* busses; libusb_context *context; libusb_init(&context); cout<<"\nUsing usb.h\n"; return 0; } and add -L <path to libs> also -I <path to header> -lusb but compiler complain: /opt/arm-2010.09/bin/../lib/gcc/arm-none-linux-gnueabi/4.5.1/../../../../arm-non e-linux-gnueabi/bin/ld: cannot find -lusb collect2: ld returned 1 exit status I'm sure I do it before this way (with different compiler). Strange. marek
I noticed that atleast the header file is being detected: with program::: #include <libusb.h> #include <iostream> using namespace std; int main() { int i=0; libusb_context *c=NULL; libusb_init(); //ERROR MADE. cout<<"\nusing libusb.h\n"; return 0; } $arm-linux-g++ usb_cc.cpp -I /home/abhinit/libusb/install/include/libusb-1.0 -o mydvr -L /home/abhinit/libusb/install/lib /home/abhinit/libusb/install/include/libusb-1.0/libusb.h: In function 'int main()': /home/abhinit/libusb/install/include/libusb-1.0/libusb.h:774: error: too few arguments to function 'int libusb_init(libusb_context**)' usb_cc.cpp:9: error: at this point in file
MY MISTAKE!!! libusb.h doesn't have those functions!!! but once I included the right functions:: #include <libusb-1.0/libusb.h> #include <iostream> using namespace std; int main() { int i=0; libusb_context **c = NULL; i = libusb_init(c); cout<<"\nusing libusb.h\n"; return 0; } I still get linker errors while using:
I guess the post got posted late :P the program u posted is right!... I'm talking about the same errors that were coming previously... also, I configured my libusb using: ./configure --host=arm-linux should it be ./configure --host=arm-linux-gnueabi ???
I used ./configure --host=arm-linux-gnueabi CC=arm-linux-gcc CXX=arm-linux-g++ ld=arm-linux-ld ranlib=arm-linux-ranlib --prefix=/home/abhinit/libusb/install I tried a test program with -lpthread and it ran smoothly! I used locate lpthread to get following useful directories: /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib/libpthread -2.9.so /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/lib/libpthread .so.0 /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/include/pt hread.h /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/include/bi ts/pthreadtypes.h /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/lib/libpth read.a /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/lib/libpth read.so /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/lib/libpth read.so_orig /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/sys-root/usr/lib/libpth read_nonshared.a /usr/include/pthread.h I even pasted my lib and headers in these folders. yet the same issue :(
you're right, libraries are not linked properly: abhinit@abhinit-laptop:~$ ldconfig -N /opt/FriendlyARM/toolschain/4.4.3/lib /sbin/ldconfig.real: Can't link /opt/FriendlyARM/toolschain/4.4.3/lib/libusb-1.0.so.0 to libusb-1.0.so any idea how to rectify this? please...
ldconfig will add path to LD_LIBRARY. maybe it fail because it's not libs for x86. Try to look for some forums maybe something with sysroot of compiler or whatever (not very familiar). marek
Dear Marek, The program finally compiled! :) instead of '-lusb' we had to use '-lusb-1.0' as I was using the libusb 1.0.8 version....!!! The executable was created... When I transfered the executable onto it and ran it, it asked for the shared library (NATURALLY): ./myprog: error while loading shared libraries: libusb-1.0.so.0: cannot open shared object file: No such file or directory I'm new to embedded development, where shall i place 'libusb-1.0.so.0' (which is offcourse cross compiled for the architecture)? Should it be placed in the folder same as that of the application? or in some other folder? can you please guide me through this. thank you!
Well! the problem has been solved. It was just needed to copy all the cross compiled lib files from libusb directory to /lib directory of mini2440! Now all programs are running! :)
THIS POST DESCRIBES SETTING UP OF LIBUSB TOOLCHAIN AND ALSO DEVELOPING APPLICATIONS TO CONTROL USB DEVICES ON MINI2440 ================================================== setting up:: download libusb latest version tar file. We are using 1.0.8 $ TOOLCHAIN=/opt/FriendlyArm/toolchain/4.4.3/arm-none-linux-gnueabi $ PATH=$PATH:$TOOLCHAIN/bin $ CC='arm-none-linux-gnueabi-gcc -march=armv4t -mtune=arm920t' $ CROSS_COMPILE=arm-none-linux-gnueabi- $ export CC CROSS_COMPILE $ tar xfv libusb-1.0.8.tar $ cd libusb-1.0.8 $ ./configure --host arm-linux $ make $ cd libusb $ cp libusb.h $TOOLCHAIN/arm-none-linux-gnueabi/include/ $ cp libusb.h $TOOLCHAIN/arm-none-linux-gnueabi/sysroot/include/ $ cp .libs/libusb-1.0.so $TOOLCHAIN/arm-none-linux-gnueabi/lib/ $ cp .libs/libusb-1.0.so $TOOLCHAIN/arm-none-linux-gnueabi/sysroot/lib/ THE TOOLCHAIN IS SET. for writing programs:: add #include<libusb.h> to use he library. compile using following:: $arm-linux-g++ myprog.cpp -o myapp -lusb-1.0 NOTE: DON'T MISSOUT ON "-lusb-1.0" Running the app on MINI2440:: copy the program on MINI2440 using FTP chmod 777 the executable copy the files in libusb-1.0.8/libusb/.libs to /lib on MINI2440 (Shared Libraries) Run the executable.
hi i want to communicate with mini2440 by ftdi viniculum using libftdi... how to make libftdi for arm?? iam trying to make simple code (simple.c,ftdi.h.ftdi.c).. but finding ftdi.c:280: error: dereferencing pointer to incomplete type i have libusb installed as mentioned in this blog and it works fine for other examples..... my make file is ========================================================= CFLAGS= -Wall -O2 CC=arm-linux-gcc -lusb-1.0 myftdi2: simple.o ftdi.o $(CC) $(CFLAGS) -o myftdi2 ftdi.o simple.o clean: rm -f myftdi2 ftdi.o simple.o ========================================================= and ftdi.c /*************************************************************************** ftdi.c - description ------------------- begin : Fri Apr 4 2003 copyright : (C) 2003-2010 by Intra2net AG email : opensource@intra2net.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License * * version 2.1 as published by the Free Software Foundation; * * * ***************************************************************************/ /** \mainpage libftdi API documentation Library to talk to FTDI chips. You find the latest versions of libftdi at http://www.intra2net.com/en/developer/libftdi/ The library is easy to use. Have a look at this short example: \include simple.c More examples can be found in the "examples" directory. */ /** \addtogroup libftdi */ /* @{ */ #include <libusb.h> #include <string.h> #include <errno.h> #include <stdio.h> #include "ftdi.h" /* stuff needed for async write */ #ifdef LIBFTDI_LINUX_ASYNC_MODE #include <sys/ioctl.h> #include <sys/time.h> #include <sys/select.h> #include <sys/types.h> #include <unistd.h> #include <linux/usbdevice_fs.h> #endif #define ftdi_error_return(code, str) do { \ ftdi->error_str = str; \ return code; \ } while(0); /** Internal function to close usb device pointer. Sets ftdi->usb_dev to NULL. \internal \param ftdi pointer to ftdi_context \retval zero if all is fine, otherwise error code from usb_close() */ static int ftdi_usb_close_internal (struct ftdi_context *ftdi) { int ret = 0; if (ftdi && ftdi->usb_dev) { ret = usb_close (ftdi->usb_dev); ftdi->usb_dev = NULL; } return ret; } /** Initializes a ftdi_context. \param ftdi pointer to ftdi_context \retval 0: all fine \retval -1: couldn't allocate read buffer \remark This should be called before all functions */ int ftdi_init(struct ftdi_context *ftdi) { unsigned int i; ftdi->usb_dev = NULL; ftdi->usb_read_timeout = 5000; ftdi->usb_write_timeout = 5000; ftdi->type = TYPE_BM; /* chip type */ ftdi->baudrate = -1; ftdi->bitbang_enabled = 0; /* 0: normal mode 1: any of the bitbang modes enabled */ ftdi->readbuffer = NULL; ftdi->readbuffer_offset = 0; ftdi->readbuffer_remaining = 0; ftdi->writebuffer_chunksize = 4096; ftdi->max_packet_size = 0; ftdi->interface = 0; ftdi->index = 0; ftdi->in_ep = 0x02; ftdi->out_ep = 0x81; ftdi->bitbang_mode = 1; /* when bitbang is enabled this holds the number of the mode */ ftdi->error_str = NULL; #ifdef LIBFTDI_LINUX_ASYNC_MODE ftdi->async_usb_buffer_size=10; if ((ftdi->async_usb_buffer=malloc(sizeof(struct usbdevfs_urb)*ftdi->async_usb_buffer_size)) == NULL) ftdi_error_return(-1, "out of memory for async usb buffer"); /* initialize async usb buffer with unused-marker */ for (i=0; i < ftdi->async_usb_buffer_size; i++) ((struct usbdevfs_urb*)ftdi->async_usb_buffer)[i].usercontext = FTDI_URB_USERCONTEXT_COOKIE; #else ftdi->async_usb_buffer_size=0; ftdi->async_usb_buffer = NULL; #endif ftdi->eeprom_size = FTDI_DEFAULT_EEPROM_SIZE; /* All fine. Now allocate the readbuffer */ return ftdi_read_data_set_chunksize(ftdi, 4096); } /** Allocate and initialize a new ftdi_context \return a pointer to a new ftdi_context, or NULL on failure */ struct ftdi_context *ftdi_new(void) { struct ftdi_context * ftdi = (struct ftdi_context *)malloc(sizeof(struct ftdi_context)); if (ftdi == NULL) { return NULL; } if (ftdi_init(ftdi) != 0) { free(ftdi); return NULL; } return ftdi; } /** Open selected channels on a chip, otherwise use first channel. \param ftdi pointer to ftdi_context \param interface Interface to use for FT2232C/2232H/4232H chips. \retval 0: all fine \retval -1: unknown interface \retval -2: USB device unavailable */ int ftdi_set_interface(struct ftdi_context *ftdi, enum ftdi_interface interface) { if (ftdi == NULL) ftdi_error_return(-2, "USB device unavailable"); switch (interface) { case INTERFACE_ANY: case INTERFACE_A: /* ftdi_usb_open_desc cares to set the right index, depending on the found chip */ break; case INTERFACE_B: ftdi->interface = 1; ftdi->index = INTERFACE_B; ftdi->in_ep = 0x04; ftdi->out_ep = 0x83; break; case INTERFACE_C: ftdi->interface = 2; ftdi->index = INTERFACE_C; ftdi->in_ep = 0x06; ftdi->out_ep = 0x85; break; case INTERFACE_D: ftdi->interface = 3; ftdi->index = INTERFACE_D; ftdi->in_ep = 0x08; ftdi->out_ep = 0x87; break; default: ftdi_error_return(-1, "Unknown interface"); } return 0; } /** Deinitializes a ftdi_context. \param ftdi pointer to ftdi_context */ void ftdi_deinit(struct ftdi_context *ftdi) { if (ftdi == NULL) return; ftdi_usb_close_internal (ftdi); if (ftdi->async_usb_buffer != NULL) { free(ftdi->async_usb_buffer); ftdi->async_usb_buffer = NULL; } if (ftdi->readbuffer != NULL) { free(ftdi->readbuffer); ftdi->readbuffer = NULL; } } /** Deinitialize and free an ftdi_context. \param ftdi pointer to ftdi_context */ void ftdi_free(struct ftdi_context *ftdi) { ftdi_deinit(ftdi); free(ftdi); } /** Use an already open libusb device. \param ftdi pointer to ftdi_context \param usb libusb usb_dev_handle to use */ /*void ftdi_set_usbdev (struct ftdi_context *ftdi, usb_dev_handle *usb) { if (ftdi == NULL) return; ftdi->usb_dev = usb; }*/ /** Finds all ftdi devices on the usb bus. Creates a new ftdi_device_list which needs to be deallocated by ftdi_list_free() after use. \param ftdi pointer to ftdi_context \param devlist Pointer where to store list of found devices \param vendor Vendor ID to search for \param product Product ID to search for \retval >0: number of devices found \retval -1: usb_find_busses() failed \retval -2: usb_find_devices() failed \retval -3: out of memory */ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devlist, int vendor, int product) { struct ftdi_device_list **curdev; struct usb_bus *bus; struct usb_device *dev; int count = 0; usb_init(); if (usb_find_busses() < 0) ftdi_error_return(-1, "usb_find_busses() failed"); if (usb_find_devices() < 0) ftdi_error_return(-2, "usb_find_devices() failed"); curdev = devlist; *curdev = 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) { *curdev = (struct ftdi_device_list*)malloc(sizeof(struct ftdi_device_list)); if (!*curdev) ftdi_error_return(-3, "out of memory"); (*curdev)->next = NULL; (*curdev)->dev = dev; curdev = &(*curdev)->next; count++; } } } return count; } /** Frees a usb device list. \param devlist USB device list created by ftdi_usb_find_all() */ void ftdi_list_free(struct ftdi_device_list **devlist) { struct ftdi_device_list *curdev, *next; for (curdev = *devlist; curdev != NULL;) { next = curdev->next; free(curdev); curdev = next; } *devlist = NULL; } /** Frees a usb device list. \param devlist USB device list created by ftdi_usb_find_all() */ void ftdi_list_free2(struct ftdi_device_list *devlist) { ftdi_list_free(&devlist); } /** Return device ID strings from the usb de...stripped-down
Thanks to Abhinit,I installed libusb-1.0.8 successfully. the error of libusb.h: No such file or directory disappeared, but usb.h the source is from: http://www.jollen.org/blog/2008/01/libusb_hello_world.html the compiler message is: /opt/FriendlyARM/toolschain/4.4.3/bin/arm-linux-gcc-4.4.3 -c -D_REENTRANT main.c -lpthread -I./ -lncurses -lusb-1.0 In file included from main.c:2: allh.h:36:17: error: usb.h: No such file or directory main.c: In function 'usbio_main': main.c:170: error: 'usb_dev_handle' undeclared (first use in this function) main.c:170: error: (Each undeclared identifier is reported only once main.c:170: error: for each function it appears in.) main.c:170: error: 'dev_handle' undeclared (first use in this function) main.c: In function 'usbio_probe': main.c:191: warning: assignment makes pointer from integer without a cast main.c:193: error: dereferencing pointer to incomplete type main.c:196: error: dereferencing pointer to incomplete type main.c:196: error: dereferencing pointer to incomplete type main.c:199: error: dereferencing pointer to incomplete type main.c:200: error: dereferencing pointer to incomplete type main.c:201: error: dereferencing pointer to incomplete type main.c:202: error: dereferencing pointer to incomplete type main.c:202: error: dereferencing pointer to incomplete type main.c: In function 'main': main.c:1780: error: dereferencing pointer to incomplete type main.c:1788: error: dereferencing pointer to incomplete type main.c:1788: error: dereferencing pointer to incomplete type make: *** [main.o] Error 1 copy_main_to_bin_folder cp: cannot stat ‘/home/mark/b1/main’: No such file or directory -rwxrwxr-x 1 mark mark 54488 9月 9 15:58 /home/mark/fA_new/mini2440/rootfs_qtopia_qt4/bin/main /home/mark/fA_new/mini2440/rootfs_qtopia_qt4/bin/main: file format elf32-littlearm architecture: arm, flags 0x00000112: EXEC_P, HAS_SYMS, D_PAGED start address 0x00008d10 can anyone help? thank you.
Hello, does anyone have a script for compiling libusb 1.0.0.20 for an ARM processor please? The autoconf configure make concludes with errors.