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}")
-fstack-protector)
add_flags(DEBUG_FLAGS
- -ggdb
- -DDEBUG=1)
+ -ggdb)
add_flags(RELEASE_FLAGS
-Wp,-D_FORTIFY_SOURCE=2)
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}")
+2014-05-15 12:33:41 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * HACKING.asciidoc: update Windows cross-build section to use libav10 (HEAD, origin/master, master)
+
+2014-05-12 23:02:28 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx-play: port to libav10
+
+2014-05-08 12:59:02 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * Update email address and copyright years
+
+2014-05-08 12:37:44 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * contrib/performance/README: fix some typos
+
+2014-05-08 12:27:23 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * cosmetics: remove some trailing spaces
+
+2014-05-08 12:26:04 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * README.asciidoc: update instructions to test libam7xxx on Windows
+
+2014-05-08 12:15:16 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * HACKING.asciidoc: update the build instructions for Windows
+
+2014-05-08 11:37:34 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx: don't use partial designated initializers
+
+2014-05-08 11:22:31 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx: add a portable_endian.h
+
+2014-05-07 21:40:44 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * Merge branch 'zoom-tele-picopix'
+
+2014-05-07 18:05:11 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx-play: allow setting the AM7XXX_ZOOM_TELE zoom mode
+
+2014-05-07 18:04:16 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * picoproj: allow setting the AM7XXX_ZOOM_TELE zoom mode
+
+2014-05-07 18:01:58 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx: implement the set_zoom_mode() operation for the PicoPix 2055
+
+2014-05-07 17:59:30 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx: add support for a new AM7XXX_ZOOM_TELE zoom mode
+
+2014-05-07 17:46:50 +0200 Antonio Ospite <ao2@ao2.it>
+
+ * am7xxx: add a msleep() implementation in tools.[ch]
+
+2013-12-04 11:32:26 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * Merge branch 'powermode-PicoPix2055'
+
+2013-11-28 15:23:04 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx: add support for setting the power mode on the PicoPix 2055
+
+2013-11-28 15:13:12 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx: dump fields of unknown packet types
+
+2013-11-28 14:57:09 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx: factor out a send_command() function
+
+2013-11-28 13:49:52 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx: switch from device quirks to device ops
+
+2013-11-18 14:41:42 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * doc/lsusb_dumps: add lsusb_Philips-PicoPix-2055.log
+
+2013-11-18 14:38:26 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * doc/lsusb_dumps: strip trailing spaces
+
+2013-11-18 14:35:37 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * doc/man: misc fixes to man pages
+
+2013-10-30 10:41:06 +0100 Antonio Ospite <ospite@studenti.unina.it>
+
+ * CMakeLists.txt: define DEBUG=1 only when CMAKE_BUILD_TYPE=Debug
+
+2013-10-13 15:50:11 +0200 Antonio Ospite <ospite@studenti.unina.it>
+
+ * HACKING.asciidoc: fix the url of the avcodec_encode_video2 patch
+
+2013-09-07 17:30:28 +0200 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx-play: cosmetics, fix coding style
+
+2013-08-03 15:14:34 +0200 Antonio Ospite <ospite@studenti.unina.it>
+
+ * am7xxx: add quirks for Philips/Sagemcom PicoPix 2055
+
+2013-07-28 23:22:15 +0200 Antonio Ospite <ospite@studenti.unina.it>
+
+ * NEWS: fix a typo s/mode/more/
+
2013-07-28 11:15:18 +0200 Antonio Ospite <ospite@studenti.unina.it>
- * 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 <ospite@studenti.unina.it>
- * 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 <ospite@studenti.unina.it>
2013-07-21 00:13:33 +0200 Antonio Ospite <ospite@studenti.unina.it>
- * 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 <ospite@studenti.unina.it>
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:
$ 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
+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
- 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
== 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:
#
# am7xxx-autodisplay - resize the screen and run am7xxx-play
#
-# Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+# Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
#
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
#
# am7xxx-play-window - show only a given window with am7xxx-play
#
-# Copyright (C) 2013 Antonio Ospite <ospite@studenti.unina.it>
+# Copyright (C) 2013-2014 Antonio Ospite <ao2@ao2.it>
#
# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
-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
/**
@mainpage libam7xxx
-@author Antonio Ospite <ospite@studenti.unina.it>
+@author Antonio Ospite <ao2@ao2.it>
@copyright GNU General Public License version 2.
Website: http://git.ao2.it/libam7xxx.git
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
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
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
--- /dev/null
+
+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
-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
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
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
EXAMPLE OF USE
--------------
-am7xxx-modeswitch
+ am7xxx-modeswitch
EXIT STATUS
COPYING
-------
-Copyright \(C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+Copyright \(C) 2012-2014 Antonio Ospite <ao2@ao2.it>
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 slave connector to be plugged in.
*-z* '<zoom mode>'::
- 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
COPYING
-------
-Copyright \(C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+Copyright \(C) 2012-2014 Antonio Ospite <ao2@ao2.it>
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 slave connector to be plugged in.
*-z* '<zoom mode>'::
- the display zoom mode, between 0 (original) and 3 (test)
+ the display zoom mode, between 0 (original) and 4 (tele)
*-W* '<image width>'::
the width of the image to upload
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
COPYING
-------
-Copyright \(C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+Copyright \(C) 2012-2014 Antonio Ospite <ao2@ao2.it>
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
/* am7xxx-modeswitch - a simple usb-modeswitch for am7xxx devices
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
/*
* am7xxx-play - play stuff on an am7xxx device (e.g. Acer C110, PicoPix 1020)
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
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 */
}
/* 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;
}
/* 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;
#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;
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,
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 <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
- AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
+ printf("\t-z <zoom mode>\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);
* 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) {
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;
}
/* picoproj - test program for libam7xxx
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
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 <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (test)\n",
- AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TEST);
+ printf("\t-z <zoom mode>\t\tthe display zoom mode, between %d (original) and %d (tele)\n",
+ AM7XXX_ZOOM_ORIGINAL, AM7XXX_ZOOM_TELE);
printf("\t-W <image width>\tthe width of the image to upload\n");
printf("\t-H <image height>\tthe height of the image to upload\n");
printf("\t-h \t\t\tthis help message\n");
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;
}
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})
/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
#include "am7xxx.h"
#include "serialize.h"
+#include "tools.h"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#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;
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",
.product_id = 0xc101,
.configuration = 2,
.interface_number = 0,
+ .ops = DEFAULT_OPS,
},
{
.name = "Acer C112",
.product_id = 0x5501,
.configuration = 2,
.interface_number = 0,
+ .ops = DEFAULT_OPS,
},
{
.name ="Aiptek PocketCinema T25",
.product_id = 0x2144,
.configuration = 2,
.interface_number = 0,
+ .ops = DEFAULT_OPS,
},
{
.name = "Philips/Sagemcom PicoPix 1020",
.product_id = 0x000e,
.configuration = 2,
.interface_number = 0,
+ .ops = DEFAULT_OPS,
},
{
.name = "Philips/Sagemcom PicoPix 2055",
.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",
.product_id = 0x0019,
.configuration = 1,
.interface_number = 0,
- .quirks = AM7XXX_QUIRK_NO_POWER_MODE | AM7XXX_QUIRK_NO_ZOOM_MODE,
},
};
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 {
#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)
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");
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
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)
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;
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);
}
/* am7xxx - communication with AM7XXX based USB Pico Projectors and DPFs
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
*
* @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;
/**
--- /dev/null
+/*
+ * 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 <endian.h>
+
+#elif defined(__APPLE__)
+
+# include <libkern/OSByteOrder.h>
+
+# define htole32(x) OSSwapHostToLittleInt32(x)
+# define le32toh(x) OSSwapLittleToHostInt32(x)
+
+#elif defined(__OpenBSD__)
+
+# include <sys/endian.h>
+
+#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+
+# include <sys/endian.h>
+
+# define le32toh(x) letoh32(x)
+
+#elif defined(__WINDOWS__)
+
+# include <winsock2.h>
+# include <sys/param.h>
+
+# 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 */
/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
#include <string.h>
-#ifdef __MINGW32__
-#define le32toh(x) (x)
-#define htole32(x) (x)
-#else
-#include <endian.h>
-#endif
-
+#include "portable_endian.h"
#include "serialize.h"
uint8_t get_8(uint8_t **bufferp)
/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
*
- * Copyright (C) 2012 Antonio Ospite <ospite@studenti.unina.it>
+ * Copyright (C) 2012-2014 Antonio Ospite <ao2@ao2.it>
*
* 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
--- /dev/null
+/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
+ *
+ * Copyright (C) 2014 Antonio Ospite <ao2@ao2.it>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <time.h>
+
+#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;
+}
--- /dev/null
+/* am7xxx - communication with AM7xxx based USB Pico Projectors and DPFs
+ *
+ * Copyright (C) 2014 Antonio Ospite <ao2@ao2.it>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TOOLS_H
+#define __TOOLS_H
+
+int msleep(unsigned long msecs);
+
+#endif /* __TOOLS_H */