From: Antonio Ospite Date: Thu, 15 May 2014 10:50:18 +0000 (+0200) Subject: Merge tag 'v0.1.5' into debian X-Git-Tag: debian/0.1.5-1~13 X-Git-Url: https://git.ao2.it/libam7xxx.git/commitdiff_plain/18abce2d438f825a38f52df6d904088adda4c890?hp=a49ffce85139aaf1fc2e2e79dd6c65ad7e7f523c Merge tag 'v0.1.5' into debian Release version 0.1.5 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index d643ed9..cb1272c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(PROJECT_DESCRIPTION set(PROJECT_VER_MAJOR 0) set(PROJECT_VER_MINOR 1) -set(PROJECT_VER_PATCH 4) +set(PROJECT_VER_PATCH 5) set(PROJECT_VER_EXTRA "") set(PROJECT_VER "${PROJECT_VER_MAJOR}.${PROJECT_VER_MINOR}.${PROJECT_VER_PATCH}${PROJECT_VER_EXTRA}") @@ -69,8 +69,7 @@ if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG) -fstack-protector) add_flags(DEBUG_FLAGS - -ggdb - -DDEBUG=1) + -ggdb) add_flags(RELEASE_FLAGS -Wp,-D_FORTIFY_SOURCE=2) @@ -105,7 +104,7 @@ if (CMAKE_COMPILER_IS_CLANG) endif() endif() -set(CMAKE_C_FLAGS_DEBUG "-O0 ${DEBUG_FLAGS} ${STRICT_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG "-O0 -DDEBUG=1 ${DEBUG_FLAGS} ${STRICT_FLAGS}") set(CMAKE_C_FLAGS_RELEASE "-O2 ${RELEASE_FLAGS} ${STRICT_FLAGS}") set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 ${RELEASE_FLAGS} ${DEBUG_FLAGS} ${STRICT_FLAGS}") diff --git a/ChangeLog b/ChangeLog index 89d4427..2e2a652 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,122 @@ +2014-05-15 12:33:41 +0200 Antonio Ospite + + * HACKING.asciidoc: update Windows cross-build section to use libav10 (HEAD, origin/master, master) + +2014-05-12 23:02:28 +0200 Antonio Ospite + + * am7xxx-play: port to libav10 + +2014-05-08 12:59:02 +0200 Antonio Ospite + + * Update email address and copyright years + +2014-05-08 12:37:44 +0200 Antonio Ospite + + * contrib/performance/README: fix some typos + +2014-05-08 12:27:23 +0200 Antonio Ospite + + * cosmetics: remove some trailing spaces + +2014-05-08 12:26:04 +0200 Antonio Ospite + + * README.asciidoc: update instructions to test libam7xxx on Windows + +2014-05-08 12:15:16 +0200 Antonio Ospite + + * HACKING.asciidoc: update the build instructions for Windows + +2014-05-08 11:37:34 +0200 Antonio Ospite + + * am7xxx: don't use partial designated initializers + +2014-05-08 11:22:31 +0200 Antonio Ospite + + * am7xxx: add a portable_endian.h + +2014-05-07 21:40:44 +0200 Antonio Ospite + + * Merge branch 'zoom-tele-picopix' + +2014-05-07 18:05:11 +0200 Antonio Ospite + + * am7xxx-play: allow setting the AM7XXX_ZOOM_TELE zoom mode + +2014-05-07 18:04:16 +0200 Antonio Ospite + + * picoproj: allow setting the AM7XXX_ZOOM_TELE zoom mode + +2014-05-07 18:01:58 +0200 Antonio Ospite + + * am7xxx: implement the set_zoom_mode() operation for the PicoPix 2055 + +2014-05-07 17:59:30 +0200 Antonio Ospite + + * am7xxx: add support for a new AM7XXX_ZOOM_TELE zoom mode + +2014-05-07 17:46:50 +0200 Antonio Ospite + + * am7xxx: add a msleep() implementation in tools.[ch] + +2013-12-04 11:32:26 +0100 Antonio Ospite + + * Merge branch 'powermode-PicoPix2055' + +2013-11-28 15:23:04 +0100 Antonio Ospite + + * am7xxx: add support for setting the power mode on the PicoPix 2055 + +2013-11-28 15:13:12 +0100 Antonio Ospite + + * am7xxx: dump fields of unknown packet types + +2013-11-28 14:57:09 +0100 Antonio Ospite + + * am7xxx: factor out a send_command() function + +2013-11-28 13:49:52 +0100 Antonio Ospite + + * am7xxx: switch from device quirks to device ops + +2013-11-18 14:41:42 +0100 Antonio Ospite + + * doc/lsusb_dumps: add lsusb_Philips-PicoPix-2055.log + +2013-11-18 14:38:26 +0100 Antonio Ospite + + * doc/lsusb_dumps: strip trailing spaces + +2013-11-18 14:35:37 +0100 Antonio Ospite + + * doc/man: misc fixes to man pages + +2013-10-30 10:41:06 +0100 Antonio Ospite + + * CMakeLists.txt: define DEBUG=1 only when CMAKE_BUILD_TYPE=Debug + +2013-10-13 15:50:11 +0200 Antonio Ospite + + * HACKING.asciidoc: fix the url of the avcodec_encode_video2 patch + +2013-09-07 17:30:28 +0200 Antonio Ospite + + * am7xxx-play: cosmetics, fix coding style + +2013-08-03 15:14:34 +0200 Antonio Ospite + + * am7xxx: add quirks for Philips/Sagemcom PicoPix 2055 + +2013-07-28 23:22:15 +0200 Antonio Ospite + + * NEWS: fix a typo s/mode/more/ + 2013-07-28 11:15:18 +0200 Antonio Ospite - * Release version 0.1.4 (HEAD, master) + * Release version 0.1.4 (tag: v0.1.4) 2013-07-28 01:11:42 +0200 Antonio Ospite - * contrib: add some benchmarking data about am7xxx_send_image_async (origin/master) + * contrib: add some benchmarking data about am7xxx_send_image_async 2013-07-28 00:50:30 +0200 Antonio Ospite @@ -76,7 +188,7 @@ 2013-07-21 00:13:33 +0200 Antonio Ospite - * am7xxx-play: use am7xxx_send_image_async() (local-ao2) + * am7xxx-play: use am7xxx_send_image_async() 2013-07-21 00:10:28 +0200 Antonio Ospite diff --git a/HACKING.asciidoc b/HACKING.asciidoc index 20c4aa2..3e55f6a 100644 --- a/HACKING.asciidoc +++ b/HACKING.asciidoc @@ -20,7 +20,7 @@ On a Debian based system, the dependencies can be installed with this command: libswscale-dev With libav/ffmpeg version previous than 0.9 this patch is needed: -http://git.ao2.it/libam7xxx.git/blob_plain/refs/heads/debian:/debian/patches/0002-Revert-am7xxx-play-switch-to-avcodec_encode_video2.patch +http://git.ao2.it/libam7xxx.git/blob_plain/refs/heads/debian:/debian/patches/0001-Revert-am7xxx-play-switch-to-avcodec_encode_video2.patch The library and the example programs can be compiled following these steps: @@ -64,17 +64,17 @@ If you want to build for MS Windows: $ sudo aptitude install mingw-w64 $ mkdir build $ cd build - $ wget -nv http://sourceforge.net/projects/libusbx/files/releases/1.0.11/Windows/libusbx-1.0.11-win.7z - $ 7z -olibusbx-1.0.11-win x libusbx-1.0.11-win.7z - $ wget -nv http://win32.libav.org/win32/libav-win32-20120521.7z - $ 7z x libav-win32-20120521.7z + $ wget -nv http://download.sourceforge.net/project/libusb/libusb-1.0/libusb-1.0.18/libusb-1.0.18-win.7z + $ 7z -olibusb-1.0.18-win x libusb-1.0.18-win.7z + $ wget -nv http://win32.libav.org/releases/libav-10.1-win32.7z + $ 7z -olibav-10.1-win32 x libav-10.1-win32.7z $ cmake \ -D GNU_HOST=i686-w64-mingw32 \ -D CMAKE_TOOLCHAIN_FILE=../cmake_modules/mingw_cross_toolchain.cmake \ -D CMAKE_INSTALL_PREFIX=libam7xxx-win/ \ - -D LIBUSB_1_INCLUDE_DIR=libusbx-1.0.11-win/include/libusbx-1.0 \ - -D LIBUSB_1_LIBRARY=libusbx-1.0.11-win/MinGW32/dll/libusb-1.0.dll \ - -D FFMPEG_ROOT=$(pwd)/libav-win32-20120521/usr \ + -D LIBUSB_1_INCLUDE_DIR=libusb-1.0.18-win/include/libusb-1.0 \ + -D LIBUSB_1_LIBRARY=libusb-1.0.18-win/MinGW32/dll/libusb-1.0.dll \ + -D FFMPEG_ROOT=$(pwd)/libav-10.1-win32/win32/usr \ ../ $ make diff --git a/NEWS b/NEWS index 7f38105..e23a882 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,18 @@ +News for v0.1.5: +================ + + * Add support for setting the power mode (i.e. brightness) on the Philips + PicoPix 2055 (Thanks to Luca Bompani) + * Add support for the "Tele" zoom mode available on the PicoPix 2055 (Thanks + to Luca Bompani) + * Fix compilation on Mac OSX + * Port am7xxx-play to libav10 + * Update instructions about compiling on Windows + News for v0.1.4: ================ - * Improved USB device configuration in order to support mode devices + * Improved USB device configuration in order to support more devices * Added support for Philips/Sagemcom PicoPix 2330 (Thanks to Grégory Lemesre) * Fixed verbose debug output diff --git a/README.asciidoc b/README.asciidoc index d11a92f..ffa2e5d 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -67,7 +67,7 @@ Examples of devices based on AM7XXX are: - Royaltek PJU-2100: * http://www.royaltek.com/index.php/pju-2100-pico-projector - + - Aiptek PocketCinema T25: * http://www.aiptek.eu/index.php/en/products/pico-projectors/pocketcinema-t25 @@ -85,18 +85,19 @@ this needs still needs to be verified. == Testing libam7xxx on MS Windows -All the needed files need to be in the same location: - - - 'libusb-1.0.dll' from http://sourceforge.net/projects/libusbx/files/releases/1.0.11/Windows/libusbx-1.0.11-win.7z +All the needed files below must be in the same location: + + - 'MinGW32/dll/libusb-1.0.dll' from + http://download.sourceforge.net/project/libusb/libusb-1.0/libusb-1.0.18/libusb-1.0.18-win.7z - 'libssp-0.dll' from MinGW; - - 'am7xxx-modeswitch.exe', 'libam7xxx.dll' and 'picoproj.exe' which can all - be built by following the instructions in the HACKING.asciidoc document - from libam7xxx. + - all the '*.dll' files from the 'win32/usr/bin/' directory in + http://win32.libav.org/releases/libav-9.13-win32.7z - - 'am7xxx-play.exe' and the '.dll' files from the 'usr/bin/' dir in libav-win32: - http://win32.libav.org/win32/libav-win32-20120521.7z + - 'am7xxx-modeswitch.exe', 'am7xxx-play.exe', 'libam7xxx.dll' and + 'picoproj.exe' which can all be built by following the instructions in the + HACKING.asciidoc document from libam7xxx. In order to use the device on MS Windows the WinUSB drivers must be installed for both the mass storage device and the display device: diff --git a/contrib/am7xxx-autodisplay.sh b/contrib/am7xxx-autodisplay.sh index 9d5199d..21ff9a3 100755 --- a/contrib/am7xxx-autodisplay.sh +++ b/contrib/am7xxx-autodisplay.sh @@ -2,7 +2,7 @@ # # am7xxx-autodisplay - resize the screen and run am7xxx-play # -# Copyright (C) 2012 Antonio Ospite +# Copyright (C) 2012-2014 Antonio Ospite # # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it diff --git a/contrib/am7xxx-play-window.sh b/contrib/am7xxx-play-window.sh index 729a72e..2978ef2 100755 --- a/contrib/am7xxx-play-window.sh +++ b/contrib/am7xxx-play-window.sh @@ -2,7 +2,7 @@ # # am7xxx-play-window - show only a given window with am7xxx-play # -# Copyright (C) 2013 Antonio Ospite +# Copyright (C) 2013-2014 Antonio Ospite # # This program is free software. It comes without any warranty, to # the extent permitted by applicable law. You can redistribute it diff --git a/contrib/performance/README b/contrib/performance/README index c00b8db..604c501 100644 --- a/contrib/performance/README +++ b/contrib/performance/README @@ -1,7 +1,7 @@ -Menchmark methodology +Benchmark methodology - Code instrumented with fps-meter - - Data acquired with this commdn line: + - Data acquired with this command line: am7xxx-play -f x11grab -i :0 -o video_size=1024x768 - Sampling repeated with either am7xxx_send_image or am7xx_send_mage_async - Results compared with ministat diff --git a/doc/DoxygenMainpage.dox b/doc/DoxygenMainpage.dox index 407cf1d..6660e27 100644 --- a/doc/DoxygenMainpage.dox +++ b/doc/DoxygenMainpage.dox @@ -1,7 +1,7 @@ /** @mainpage libam7xxx -@author Antonio Ospite +@author Antonio Ospite @copyright GNU General Public License version 2. Website: http://git.ao2.it/libam7xxx.git diff --git a/doc/lsusb_dumps/lsusb_Acer-C110.log b/doc/lsusb_dumps/lsusb_Acer-C110.log index 53f74e2..88a1639 100644 --- a/doc/lsusb_dumps/lsusb_Acer-C110.log +++ b/doc/lsusb_dumps/lsusb_Acer-C110.log @@ -5,8 +5,8 @@ Device Descriptor: bDescriptorType 1 bcdUSB 2.00 bDeviceClass 255 Vendor Specific Class - bDeviceSubClass 0 - bDeviceProtocol 0 + bDeviceSubClass 0 + bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0x1de1 Actions Microelectronics Co. idProduct 0xc101 Generic Display Device @@ -32,8 +32,8 @@ Device Descriptor: bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 255 Vendor Specific Class - bInterfaceSubClass 8 - bInterfaceProtocol 8 + bInterfaceSubClass 8 + bInterfaceProtocol 8 iInterface 7 USB PICO Endpoint Descriptor: bLength 7 @@ -60,8 +60,8 @@ Device Qualifier (for other device speed): bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) - bDeviceSubClass 0 - bDeviceProtocol 0 + bDeviceSubClass 0 + bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1 Device Status: 0x0001 diff --git a/doc/lsusb_dumps/lsusb_Philips-PicoPix-2055.log b/doc/lsusb_dumps/lsusb_Philips-PicoPix-2055.log new file mode 100644 index 0000000..2346e7f --- /dev/null +++ b/doc/lsusb_dumps/lsusb_Philips-PicoPix-2055.log @@ -0,0 +1,68 @@ + +Bus 003 Device 040: ID 21e7:0016 +Device Descriptor: + bLength 18 + bDescriptorType 1 + bcdUSB 2.00 + bDeviceClass 255 Vendor Specific Class + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + idVendor 0x21e7 + idProduct 0x0016 + bcdDevice 1.00 + iManufacturer 1 actions + iProduct 2 Usb Device + iSerial 3 00000000000000000000000000000000 + bNumConfigurations 1 + Configuration Descriptor: + bLength 9 + bDescriptorType 2 + wTotalLength 32 + bNumInterfaces 1 + bConfigurationValue 2 + iConfiguration 6 PICO PROJECTOR + bmAttributes 0xc0 + Self Powered + MaxPower 2mA + Interface Descriptor: + bLength 9 + bDescriptorType 4 + bInterfaceNumber 0 + bAlternateSetting 0 + bNumEndpoints 2 + bInterfaceClass 255 Vendor Specific Class + bInterfaceSubClass 8 + bInterfaceProtocol 8 + iInterface 7 USB PICO + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x81 EP 1 IN + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 0 + Endpoint Descriptor: + bLength 7 + bDescriptorType 5 + bEndpointAddress 0x01 EP 1 OUT + bmAttributes 2 + Transfer Type Bulk + Synch Type None + Usage Type Data + wMaxPacketSize 0x0200 1x 512 bytes + bInterval 1 +Device Qualifier (for other device speed): + bLength 10 + bDescriptorType 6 + bcdUSB 2.00 + bDeviceClass 0 (Defined at Interface level) + bDeviceSubClass 0 + bDeviceProtocol 0 + bMaxPacketSize0 64 + bNumConfigurations 1 +Device Status: 0x0001 + Self Powered diff --git a/doc/lsusb_dumps/lsusb_Philips-PicoPix-2330.log b/doc/lsusb_dumps/lsusb_Philips-PicoPix-2330.log index fc57c0d..3a7c3dc 100644 --- a/doc/lsusb_dumps/lsusb_Philips-PicoPix-2330.log +++ b/doc/lsusb_dumps/lsusb_Philips-PicoPix-2330.log @@ -1,15 +1,15 @@ -Bus 002 Device 004: ID 21e7:0019 +Bus 002 Device 004: ID 21e7:0019 Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 255 Vendor Specific Class - bDeviceSubClass 0 - bDeviceProtocol 0 + bDeviceSubClass 0 + bDeviceProtocol 0 bMaxPacketSize0 64 - idVendor 0x21e7 - idProduct 0x0019 + idVendor 0x21e7 + idProduct 0x0019 bcdDevice 0.00 iManufacturer 1 actions-micro iProduct 2 actions-subdisplay @@ -32,8 +32,8 @@ Device Descriptor: bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 255 Vendor Specific Class - bInterfaceSubClass 0 - bInterfaceProtocol 0 + bInterfaceSubClass 0 + bInterfaceProtocol 0 iInterface 5 vendor subdisp Endpoint Descriptor: bLength 7 @@ -60,8 +60,8 @@ Device Qualifier (for other device speed): bDescriptorType 6 bcdUSB 2.00 bDeviceClass 0 (Defined at Interface level) - bDeviceSubClass 0 - bDeviceProtocol 0 + bDeviceSubClass 0 + bDeviceProtocol 0 bMaxPacketSize0 64 bNumConfigurations 1 Device Status: 0x0001 diff --git a/doc/man/am7xxx-modeswitch.1.txt b/doc/man/am7xxx-modeswitch.1.txt index 20dfd29..b5ebe05 100644 --- a/doc/man/am7xxx-modeswitch.1.txt +++ b/doc/man/am7xxx-modeswitch.1.txt @@ -25,7 +25,7 @@ It is handy on systems where usb-modeswitch is not available, like Windows. EXAMPLE OF USE -------------- -am7xxx-modeswitch + am7xxx-modeswitch EXIT STATUS @@ -49,7 +49,7 @@ Main web site: COPYING ------- -Copyright \(C) 2012 Antonio Ospite +Copyright \(C) 2012-2014 Antonio Ospite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/doc/man/am7xxx-play.1.txt b/doc/man/am7xxx-play.1.txt index eabdb9c..ae20974 100644 --- a/doc/man/am7xxx-play.1.txt +++ b/doc/man/am7xxx-play.1.txt @@ -63,10 +63,10 @@ EXAMPLE: the slave connector to be plugged in. *-z* '':: - the display zoom mode, between 0 (original) and 3 (test) + the display zoom mode, between 0 (original) and 4 (tele) *-h*:: - this help message + show the help message EXAMPLES OF USE @@ -99,7 +99,7 @@ Main web site: COPYING ------- -Copyright \(C) 2012 Antonio Ospite +Copyright \(C) 2012-2014 Antonio Ospite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/doc/man/picoproj.1.txt b/doc/man/picoproj.1.txt index 0fea153..c4c095e 100644 --- a/doc/man/picoproj.1.txt +++ b/doc/man/picoproj.1.txt @@ -46,7 +46,7 @@ OPTIONS the slave connector to be plugged in. *-z* '':: - the display zoom mode, between 0 (original) and 3 (test) + the display zoom mode, between 0 (original) and 4 (tele) *-W* '':: the width of the image to upload @@ -55,13 +55,13 @@ OPTIONS the height of the image to upload *-h*:: - this help message + show the help message EXAMPLE OF USE -------------- -picoproj -f file.jpg -F 1 -l 5 -W 800 -H 480 + picoproj -f file.jpg -F 1 -l 5 -W 800 -H 480 EXIT STATUS @@ -85,7 +85,7 @@ Main web site: COPYING ------- -Copyright \(C) 2012 Antonio Ospite +Copyright \(C) 2012-2014 Antonio Ospite This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/examples/am7xxx-modeswitch.c b/examples/am7xxx-modeswitch.c index 9942d81..a66c37d 100644 --- a/examples/am7xxx-modeswitch.c +++ b/examples/am7xxx-modeswitch.c @@ -1,6 +1,6 @@ /* am7xxx-modeswitch - a simple usb-modeswitch for am7xxx devices * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/examples/am7xxx-play.c b/examples/am7xxx-play.c index 3230e67..2fa615a 100644 --- a/examples/am7xxx-play.c +++ b/examples/am7xxx-play.c @@ -1,7 +1,7 @@ /* * am7xxx-play - play stuff on an am7xxx device (e.g. Acer C110, PicoPix 1020) * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -223,8 +223,8 @@ static int video_output_init(struct video_output_ctx *output_ctx, goto out; } - output_codec_ctx->pix_fmt = PIX_FMT_YUVJ420P; - output_codec_ctx->codec_id = CODEC_ID_MJPEG; + output_codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P; + output_codec_ctx->codec_id = AV_CODEC_ID_MJPEG; output_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO; /* Set quality and other VBR settings */ @@ -306,7 +306,7 @@ static int am7xxx_play(const char *input_format_string, } /* allocate an input frame */ - picture_raw = avcodec_alloc_frame(); + picture_raw = av_frame_alloc(); if (picture_raw == NULL) { fprintf(stderr, "cannot allocate the raw picture frame!\n"); ret = -ENOMEM; @@ -314,7 +314,7 @@ static int am7xxx_play(const char *input_format_string, } /* allocate output frame */ - picture_scaled = avcodec_alloc_frame(); + picture_scaled = av_frame_alloc(); if (picture_scaled == NULL) { fprintf(stderr, "cannot allocate the scaled picture!\n"); ret = -ENOMEM; @@ -428,11 +428,11 @@ static int am7xxx_play(const char *input_format_string, #endif ret = am7xxx_send_image_async(dev, - image_format, - (output_ctx.codec_ctx)->width, - (output_ctx.codec_ctx)->height, - out_picture, - out_picture_size); + image_format, + (output_ctx.codec_ctx)->width, + (output_ctx.codec_ctx)->height, + out_picture, + out_picture_size); if (ret < 0) { perror("am7xxx_send_image"); run = 0; @@ -449,9 +449,9 @@ end_while: cleanup_out_buf: av_free(out_buf); cleanup_picture_scaled: - av_free(picture_scaled); + av_frame_free(&picture_scaled); cleanup_picture_raw: - av_free(picture_raw); + av_frame_free(&picture_raw); cleanup_output: /* av_free is needed as well, @@ -610,8 +610,8 @@ static void usage(char *name) AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO); printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n"); printf("\t\t\t\t the slave connector to be plugged in.\n"); - printf("\t-z \t\tthe display zoom mode, between %d (original) and %d (test)\n", - AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST); + printf("\t-z \t\tthe display zoom mode, between %d (original) and %d (tele)\n", + AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TELE); printf("\t-h \t\t\tthis help message\n"); printf("\n\nEXAMPLES OF USE:\n"); printf("\t%s -f x11grab -i :0.0 -o video_size=800x480\n", name); @@ -665,7 +665,7 @@ int main(int argc, char *argv[]) * draw_mouse=1,framerate=100,video_size=800x480 */ subopts = subopts_saved = strdup(optarg); - while((subopt = strtok_r(subopts, ",", &subopts))) { + while ((subopt = strtok_r(subopts, ",", &subopts))) { char *subopt_name = strtok_r(subopt, "=", &subopt); char *subopt_value = strtok_r(NULL, "", &subopt); if (subopt_value == NULL) { @@ -757,11 +757,12 @@ int main(int argc, char *argv[]) case AM7XXX_ZOOM_H: case AM7XXX_ZOOM_H_V: case AM7XXX_ZOOM_TEST: + case AM7XXX_ZOOM_TELE: fprintf(stdout, "Zoom: %d\n", zoom); break; default: fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n", - AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST); + AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TELE); ret = -EINVAL; goto out; } diff --git a/examples/picoproj.c b/examples/picoproj.c index 9128538..d335ed1 100644 --- a/examples/picoproj.c +++ b/examples/picoproj.c @@ -1,6 +1,6 @@ /* picoproj - test program for libam7xxx * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,8 +47,8 @@ static void usage(char *name) AM7XXX_POWER_OFF, AM7XXX_POWER_TURBO); printf("\t\t\t\tWARNING: Level 2 and greater require the master AND\n"); printf("\t\t\t\t the slave connector to be plugged in.\n"); - printf("\t-z \t\tthe display zoom mode, between %d (original) and %d (test)\n", - AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST); + printf("\t-z \t\tthe display zoom mode, between %d (original) and %d (tele)\n", + AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TELE); printf("\t-W \tthe width of the image to upload\n"); printf("\t-H \tthe height of the image to upload\n"); printf("\t-h \t\t\tthis help message\n"); @@ -138,11 +138,12 @@ int main(int argc, char *argv[]) case AM7XXX_ZOOM_H: case AM7XXX_ZOOM_H_V: case AM7XXX_ZOOM_TEST: + case AM7XXX_ZOOM_TELE: fprintf(stdout, "Zoom: %d\n", zoom); break; default: fprintf(stderr, "Invalid zoom mode value, must be between %d and %d\n", - AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST); + AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TELE); ret = -EINVAL; goto out; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0817374..f743b1a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,11 @@ add_definitions("-D_BSD_SOURCE") # for htole32() +add_definitions("-D_POSIX_C_SOURCE=199309L") # for nanosleep() # Find packages needed to build library find_package(libusb-1.0 REQUIRED) include_directories(${LIBUSB_1_INCLUDE_DIRS}) -set(SRC am7xxx.c serialize.c) +set(SRC am7xxx.c serialize.c tools.c) # Build the library add_library(am7xxx SHARED ${SRC}) diff --git a/src/am7xxx.c b/src/am7xxx.c index 5b1e35a..ebc403e 100644 --- a/src/am7xxx.c +++ b/src/am7xxx.c @@ -1,6 +1,6 @@ /* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "am7xxx.h" #include "serialize.h" +#include "tools.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -64,8 +65,10 @@ static void log_message(am7xxx_context *ctx, #define debug(ctx, ...) log_message(ctx, AM7XXX_LOG_DEBUG, __func__, 0, __VA_ARGS__) #define trace(ctx, ...) log_message(ctx, AM7XXX_LOG_TRACE, NULL, 0, __VA_ARGS__) -#define AM7XXX_QUIRK_NO_POWER_MODE (1 << 0) -#define AM7XXX_QUIRK_NO_ZOOM_MODE (1 << 1) +struct am7xxx_ops { + int (*set_power_mode)(am7xxx_device *dev, am7xxx_power_mode power); + int (*set_zoom_mode)(am7xxx_device *dev, am7xxx_zoom_mode zoom); +}; struct am7xxx_usb_device_descriptor { const char *name; @@ -73,9 +76,19 @@ struct am7xxx_usb_device_descriptor { uint16_t product_id; uint8_t configuration; /* The bConfigurationValue of the device */ uint8_t interface_number; /* The bInterfaceNumber of the device */ - unsigned long quirks; + struct am7xxx_ops ops; }; +static int default_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power); +static int picopix_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power); +static int default_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom); +static int picopix_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom); + +#define DEFAULT_OPS { \ + .set_power_mode = default_set_power_mode, \ + .set_zoom_mode = default_set_zoom_mode, \ +} + static const struct am7xxx_usb_device_descriptor supported_devices[] = { { .name = "Acer C110", @@ -83,6 +96,7 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0xc101, .configuration = 2, .interface_number = 0, + .ops = DEFAULT_OPS, }, { .name = "Acer C112", @@ -90,6 +104,7 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0x5501, .configuration = 2, .interface_number = 0, + .ops = DEFAULT_OPS, }, { .name ="Aiptek PocketCinema T25", @@ -97,6 +112,7 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0x2144, .configuration = 2, .interface_number = 0, + .ops = DEFAULT_OPS, }, { .name = "Philips/Sagemcom PicoPix 1020", @@ -104,6 +120,7 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0x000e, .configuration = 2, .interface_number = 0, + .ops = DEFAULT_OPS, }, { .name = "Philips/Sagemcom PicoPix 2055", @@ -111,6 +128,10 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0x0016, .configuration = 2, .interface_number = 0, + .ops = { + .set_power_mode = picopix_set_power_mode, + .set_zoom_mode = picopix_set_zoom_mode, + }, }, { .name = "Philips/Sagemcom PicoPix 2330", @@ -118,7 +139,6 @@ static const struct am7xxx_usb_device_descriptor supported_devices[] = { .product_id = 0x0019, .configuration = 1, .interface_number = 0, - .quirks = AM7XXX_QUIRK_NO_POWER_MODE | AM7XXX_QUIRK_NO_ZOOM_MODE, }, }; @@ -150,6 +170,11 @@ typedef enum { AM7XXX_PACKET_TYPE_IMAGE = 0x02, AM7XXX_PACKET_TYPE_POWER = 0x04, AM7XXX_PACKET_TYPE_ZOOM = 0x05, + AM7XXX_PACKET_TYPE_PICOPIX_POWER_LOW = 0x15, + AM7XXX_PACKET_TYPE_PICOPIX_POWER_MEDIUM = 0x16, + AM7XXX_PACKET_TYPE_PICOPIX_POWER_HIGH = 0x17, + AM7XXX_PACKET_TYPE_PICOPIX_ENABLE_TI = 0x18, + AM7XXX_PACKET_TYPE_PICOPIX_DISABLE_TI = 0x19, } am7xxx_packet_type; struct am7xxx_generic_header { @@ -215,6 +240,18 @@ struct am7xxx_header { #ifdef DEBUG +static void debug_dump_generic_header(am7xxx_context *ctx, struct am7xxx_generic_header *g) +{ + if (ctx == NULL || g == NULL) + return; + + debug(ctx, "Generic header:\n"); + debug(ctx, "\tfield0: 0x%08x (%u)\n", g->field0, g->field0); + debug(ctx, "\tfield1: 0x%08x (%u)\n", g->field1, g->field1); + debug(ctx, "\tfield2: 0x%08x (%u)\n", g->field2, g->field2); + debug(ctx, "\tfield3: 0x%08x (%u)\n", g->field3, g->field3); +} + static void debug_dump_devinfo_header(am7xxx_context *ctx, struct am7xxx_devinfo_header *d) { if (ctx == NULL || d == NULL) @@ -293,7 +330,8 @@ static void debug_dump_header(am7xxx_context *ctx, struct am7xxx_header *h) break; default: - debug(ctx, "Packet type not supported!\n"); + debug(ctx, "Parsing data not supported for this packet type!\n"); + debug_dump_generic_header(ctx, &(h->header_data.data)); break; } debug(ctx, "END\n\n"); @@ -560,6 +598,28 @@ static int send_header(am7xxx_device *dev, struct am7xxx_header *h) return ret; } +static int send_command(am7xxx_device *dev, am7xxx_packet_type type) +{ + struct am7xxx_header h = { + .packet_type = type, + .direction = AM7XXX_DIRECTION_OUT, + .header_data_len = 0x00, + .unknown2 = 0x3e, + .unknown3 = 0x10, + .header_data = { + .data = { + .field0 = 0, + .field1 = 0, + .field2 = 0, + .field3 = 0, + }, + }, + }; + + return send_header(dev, &h); +} + + /* When level == AM7XXX_LOG_FATAL do not check the log_level from the context * and print the message unconditionally, this makes it possible to print * fatal messages even early on initialization, before the context has been @@ -786,6 +846,162 @@ out: return ret; } +/* Device specific operations */ + +static int default_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power) +{ + int ret; + struct am7xxx_header h = { + .packet_type = AM7XXX_PACKET_TYPE_POWER, + .direction = AM7XXX_DIRECTION_OUT, + .header_data_len = sizeof(struct am7xxx_power_header), + .unknown2 = 0x3e, + .unknown3 = 0x10, + }; + + switch(power) { + case AM7XXX_POWER_OFF: + h.header_data.power.bit2 = 0; + h.header_data.power.bit1 = 0; + h.header_data.power.bit0 = 0; + break; + + case AM7XXX_POWER_LOW: + h.header_data.power.bit2 = 0; + h.header_data.power.bit1 = 0; + h.header_data.power.bit0 = 1; + break; + + case AM7XXX_POWER_MIDDLE: + h.header_data.power.bit2 = 0; + h.header_data.power.bit1 = 1; + h.header_data.power.bit0 = 0; + break; + + case AM7XXX_POWER_HIGH: + h.header_data.power.bit2 = 0; + h.header_data.power.bit1 = 1; + h.header_data.power.bit0 = 1; + break; + + case AM7XXX_POWER_TURBO: + h.header_data.power.bit2 = 1; + h.header_data.power.bit1 = 0; + h.header_data.power.bit0 = 0; + break; + + default: + error(dev->ctx, "Unsupported power mode.\n"); + return -EINVAL; + }; + + ret = send_header(dev, &h); + if (ret < 0) + return ret; + + return 0; +} + +static int picopix_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power) +{ + switch(power) { + case AM7XXX_POWER_LOW: + return send_command(dev, AM7XXX_PACKET_TYPE_PICOPIX_POWER_LOW); + + case AM7XXX_POWER_MIDDLE: + return send_command(dev, AM7XXX_PACKET_TYPE_PICOPIX_POWER_MEDIUM); + + case AM7XXX_POWER_HIGH: + return send_command(dev, AM7XXX_PACKET_TYPE_PICOPIX_POWER_HIGH); + + case AM7XXX_POWER_OFF: + case AM7XXX_POWER_TURBO: + default: + error(dev->ctx, "Unsupported power mode.\n"); + return -EINVAL; + }; +} + +static int default_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom) +{ + int ret; + struct am7xxx_header h = { + .packet_type = AM7XXX_PACKET_TYPE_ZOOM, + .direction = AM7XXX_DIRECTION_OUT, + .header_data_len = sizeof(struct am7xxx_zoom_header), + .unknown2 = 0x3e, + .unknown3 = 0x10, + }; + + switch(zoom) { + case AM7XXX_ZOOM_ORIGINAL: + h.header_data.zoom.bit1 = 0; + h.header_data.zoom.bit0 = 0; + break; + + case AM7XXX_ZOOM_H: + h.header_data.zoom.bit1 = 0; + h.header_data.zoom.bit0 = 1; + break; + + case AM7XXX_ZOOM_H_V: + h.header_data.zoom.bit1 = 1; + h.header_data.zoom.bit0 = 0; + break; + + case AM7XXX_ZOOM_TEST: + h.header_data.zoom.bit1 = 1; + h.header_data.zoom.bit0 = 1; + break; + + case AM7XXX_ZOOM_TELE: + default: + error(dev->ctx, "Unsupported zoom mode.\n"); + return -EINVAL; + }; + + ret = send_header(dev, &h); + if (ret < 0) + return ret; + + return 0; +} + +static int picopix_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom) +{ + int ret; + am7xxx_packet_type packet_type; + + switch(zoom) { + case AM7XXX_ZOOM_ORIGINAL: + packet_type = AM7XXX_PACKET_TYPE_PICOPIX_DISABLE_TI; + break; + + case AM7XXX_ZOOM_TELE: + packet_type = AM7XXX_PACKET_TYPE_PICOPIX_ENABLE_TI; + break; + + case AM7XXX_ZOOM_H: + case AM7XXX_ZOOM_H_V: + case AM7XXX_ZOOM_TEST: + default: + error(dev->ctx, "Unsupported zoom mode.\n"); + return -EINVAL; + }; + + ret = send_command(dev, packet_type); + if (ret < 0) + return ret; + + /* The Windows drivers wait for 100ms and send the same command again, + * probably to overcome a firmware deficiency */ + ret = msleep(100); + if (ret < 0) + return ret; + + return send_command(dev, packet_type); +} + /* Public API */ AM7XXX_PUBLIC int am7xxx_init(am7xxx_context **ctx) @@ -912,31 +1128,18 @@ AM7XXX_PUBLIC int am7xxx_get_device_info(am7xxx_device *dev, am7xxx_device_info *device_info) { int ret; - struct am7xxx_header h = { - .packet_type = AM7XXX_PACKET_TYPE_DEVINFO, - .direction = AM7XXX_DIRECTION_OUT, - .header_data_len = 0x00, - .unknown2 = 0x3e, - .unknown3 = 0x10, - .header_data = { - .devinfo = { - .native_width = 0, - .native_height = 0, - .unknown0 = 0, - .unknown1 = 0, - }, - }, - }; + struct am7xxx_header h; if (dev->device_info) { memcpy(device_info, dev->device_info, sizeof(*device_info)); return 0; } - ret = send_header(dev, &h); + ret = send_command(dev, AM7XXX_PACKET_TYPE_DEVINFO); if (ret < 0) return ret; + memset(&h, 0, sizeof(h)); ret = read_header(dev, &h); if (ret < 0) return ret; @@ -1103,110 +1306,22 @@ AM7XXX_PUBLIC int am7xxx_send_image_async(am7xxx_device *dev, AM7XXX_PUBLIC int am7xxx_set_power_mode(am7xxx_device *dev, am7xxx_power_mode power) { - int ret; - struct am7xxx_header h = { - .packet_type = AM7XXX_PACKET_TYPE_POWER, - .direction = AM7XXX_DIRECTION_OUT, - .header_data_len = sizeof(struct am7xxx_power_header), - .unknown2 = 0x3e, - .unknown3 = 0x10, - }; - - if (dev->desc->quirks & AM7XXX_QUIRK_NO_POWER_MODE) { - debug(dev->ctx, - "setting power mode is unsupported on this device\n"); + if (dev->desc->ops.set_power_mode == NULL) { + warning(dev->ctx, + "setting power mode is unsupported on this device\n"); return 0; } - switch(power) { - case AM7XXX_POWER_OFF: - h.header_data.power.bit2 = 0; - h.header_data.power.bit1 = 0; - h.header_data.power.bit0 = 0; - break; - - case AM7XXX_POWER_LOW: - h.header_data.power.bit2 = 0; - h.header_data.power.bit1 = 0; - h.header_data.power.bit0 = 1; - break; - - case AM7XXX_POWER_MIDDLE: - h.header_data.power.bit2 = 0; - h.header_data.power.bit1 = 1; - h.header_data.power.bit0 = 0; - break; - - case AM7XXX_POWER_HIGH: - h.header_data.power.bit2 = 0; - h.header_data.power.bit1 = 1; - h.header_data.power.bit0 = 1; - break; - - case AM7XXX_POWER_TURBO: - h.header_data.power.bit2 = 1; - h.header_data.power.bit1 = 0; - h.header_data.power.bit0 = 0; - break; - - default: - error(dev->ctx, "Unsupported power mode.\n"); - return -EINVAL; - }; - - ret = send_header(dev, &h); - if (ret < 0) - return ret; - - return 0; + return dev->desc->ops.set_power_mode(dev, power); } AM7XXX_PUBLIC int am7xxx_set_zoom_mode(am7xxx_device *dev, am7xxx_zoom_mode zoom) { - int ret; - struct am7xxx_header h = { - .packet_type = AM7XXX_PACKET_TYPE_ZOOM, - .direction = AM7XXX_DIRECTION_OUT, - .header_data_len = sizeof(struct am7xxx_zoom_header), - .unknown2 = 0x3e, - .unknown3 = 0x10, - }; - - if (dev->desc->quirks & AM7XXX_QUIRK_NO_ZOOM_MODE) { - debug(dev->ctx, - "setting zoom mode is unsupported on this device\n"); + if (dev->desc->ops.set_zoom_mode == NULL) { + warning(dev->ctx, + "setting zoom mode is unsupported on this device\n"); return 0; } - switch(zoom) { - case AM7XXX_ZOOM_ORIGINAL: - h.header_data.zoom.bit1 = 0; - h.header_data.zoom.bit0 = 0; - break; - - case AM7XXX_ZOOM_H: - h.header_data.zoom.bit1 = 0; - h.header_data.zoom.bit0 = 1; - break; - - case AM7XXX_ZOOM_H_V: - h.header_data.zoom.bit1 = 1; - h.header_data.zoom.bit0 = 0; - break; - - case AM7XXX_ZOOM_TEST: - h.header_data.zoom.bit1 = 1; - h.header_data.zoom.bit0 = 1; - break; - - default: - error(dev->ctx, "Unsupported zoom mode.\n"); - return -EINVAL; - }; - - ret = send_header(dev, &h); - if (ret < 0) - return ret; - - return 0; + return dev->desc->ops.set_zoom_mode(dev, zoom); } diff --git a/src/am7xxx.h b/src/am7xxx.h index ec9869d..4a97f69 100644 --- a/src/am7xxx.h +++ b/src/am7xxx.h @@ -1,6 +1,6 @@ /* am7xxx - communication with AM7XXX based USB Pico Projectors and DPFs * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -114,12 +114,17 @@ typedef enum { * * @note On the zoom test screen the version of the firmware running on the * device is shown as well (e.g SPI_V21.0.0_2011.03.18). + * + * @note The Tele mode is available only on some PicoPix models, when using it + * the image is distorted like if a different lens was used, but the global + * aspect ratio of the image does not change. */ typedef enum { AM7XXX_ZOOM_ORIGINAL = 0, /**< Original Size, as retrieved via #am7xxx_device_info. */ AM7XXX_ZOOM_H = 1, /**< Zoom 1: H Scale (changes aspect ratio). */ AM7XXX_ZOOM_H_V = 2, /**< Zoom 2: H/V Scale (changes aspect ratio). */ AM7XXX_ZOOM_TEST = 3, /**< Zoom test screen, the firmware version is shown as well. */ + AM7XXX_ZOOM_TELE = 4, /**< Zoom Tele: available on some PicoPix models. */ } am7xxx_zoom_mode; /** diff --git a/src/portable_endian.h b/src/portable_endian.h new file mode 100644 index 0000000..1741f18 --- /dev/null +++ b/src/portable_endian.h @@ -0,0 +1,65 @@ +/* + * Public domain, stripped down version of: + * https://gist.github.com/panzi/6856583 + */ + +#ifndef __PORTABLE_ENDIAN_H +#define __PORTABLE_ENDIAN_H + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htole32(x) OSSwapHostToLittleInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define le32toh(x) letoh32(x) + +#elif defined(__WINDOWS__) + +# include +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htole32(x) (x) +# define le32toh(x) (x) + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ + +# define htole32(x) __builtin_bswap32(x) +# define le32toh(x) __builtin_bswap32(x) + +# else + +# error byte order not supported + +# endif + +#else + +#error platform not supported + +#endif + +#endif /* __PORTABLE_ENDIAN_H */ diff --git a/src/serialize.c b/src/serialize.c index 72e3fd4..0a1c2fd 100644 --- a/src/serialize.c +++ b/src/serialize.c @@ -1,6 +1,6 @@ /* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,13 +18,7 @@ #include -#ifdef __MINGW32__ -#define le32toh(x) (x) -#define htole32(x) (x) -#else -#include -#endif - +#include "portable_endian.h" #include "serialize.h" uint8_t get_8(uint8_t **bufferp) diff --git a/src/serialize.h b/src/serialize.h index f1869c9..c109172 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -1,6 +1,6 @@ /* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs * - * Copyright (C) 2012 Antonio Ospite + * Copyright (C) 2012-2014 Antonio Ospite * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 0000000..be63ac6 --- /dev/null +++ b/src/tools.c @@ -0,0 +1,48 @@ +/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs + * + * Copyright (C) 2014 Antonio Ospite + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "tools.h" + +/** + * Sleep for a period expressed in milliseconds + * + * @param[in] msecs Time to sleep in milliseconds + * + * @return 0 on success, -1 on error + */ +int msleep(unsigned long msecs) +{ + struct timespec delay; + int ret; + + delay.tv_sec = msecs / 1000; + delay.tv_nsec = (msecs % 1000) * 1000000; + while (1) { + ret = nanosleep(&delay, &delay); + if (ret == -1 && errno == EINTR) + continue; + break; + } + if (ret == -1) + return ret; + + return 0; +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 0000000..d3140c8 --- /dev/null +++ b/src/tools.h @@ -0,0 +1,24 @@ +/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs + * + * Copyright (C) 2014 Antonio Ospite + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __TOOLS_H +#define __TOOLS_H + +int msleep(unsigned long msecs); + +#endif /* __TOOLS_H */