├── .gitignore ├── Android.mk ├── Makefile ├── battery_test.c ├── camera.cpp ├── camera.h ├── cameraParams.cpp ├── cameraParams.h ├── camera_to_fb2.cpp ├── camera_to_v4l.cpp ├── clean_devregs.php ├── debugPrint.h ├── devregs.cpp ├── devregs_imx51.dat ├── devregs_imx53.dat ├── devregs_imx6x.dat ├── fb2_overlay.cpp ├── fb2_overlay.h ├── fbSet.cpp ├── flipper.cpp ├── fourcc.cpp ├── fourcc.h ├── hexDump.cpp ├── hexDump.h ├── imx_h264_encoder.cpp ├── imx_h264_encoder.h ├── imx_mjpeg_encoder.cpp ├── imx_mjpeg_encoder.h ├── imx_mpeg4_encoder.cpp ├── imx_mpeg4_encoder.h ├── imx_vpu.cpp ├── imx_vpu.h ├── inputRead.cpp ├── input_mt_read.cpp ├── inputattach.c ├── ipu_bufs.cpp ├── libjpeg_encoder.cpp ├── libjpeg_encoder.h ├── makeVersion.sh ├── memcopy.S ├── multimeter.cpp ├── ov5640 ├── physMem.cpp ├── physMem.h ├── pmic.cpp ├── savembrs.c ├── spidev.h ├── tickMs.h ├── v4l_display.cpp └── v4l_display.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | camera_to_fb2 3 | devregs 4 | *.a 5 | version.h 6 | fb2_overlay 7 | devregs 8 | version.h 9 | pmic 10 | ipu_bufs 11 | battery_test 12 | ipu_bufs_mx51 13 | ipu_bufs_mx53 14 | imx_h264_encoder 15 | imx_mpeg4_encoder 16 | camera_to_v4l 17 | inputRead 18 | savembrs 19 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | 2 | LOCAL_PATH:= $(call my-dir) 3 | 4 | include $(CLEAR_VARS) 5 | LOCAL_MODULE_TAGS := eng 6 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 7 | LOCAL_CPPFLAGS += -I$(LOCAL_PATH)/../../external/linux-lib/vpu/ 8 | LOCAL_SRC_FILES := camera.cpp cameraParams.cpp fb2_overlay.cpp fourcc.cpp hexDump.cpp memcopy.S v4l_display.cpp 9 | LOCAL_MODULE := libbdhw 10 | include $(BUILD_STATIC_LIBRARY) 11 | 12 | include $(CLEAR_VARS) 13 | 14 | LOCAL_MODULE_TAGS := eng 15 | LOCAL_SRC_FILES:=devregs.cpp 16 | LOCAL_MODULE:=devregs 17 | LOCAL_CPPFLAGS += -DANDROID 18 | LOCAL_SHARED_LIBRARIES:=libc 19 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 20 | include $(BUILD_EXECUTABLE) 21 | 22 | include $(CLEAR_VARS) 23 | 24 | LOCAL_MODULE_TAGS := eng 25 | LOCAL_SRC_FILES:=inputattach.c 26 | LOCAL_MODULE:=inputattach 27 | LOCAL_CPPFLAGS += -DANDROID 28 | LOCAL_SHARED_LIBRARIES:=libc 29 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 30 | include $(BUILD_EXECUTABLE) 31 | 32 | include $(CLEAR_VARS) 33 | 34 | LOCAL_MODULE_TAGS := eng 35 | LOCAL_SRC_FILES:=input_mt_read.cpp 36 | LOCAL_MODULE:=input_mt_read 37 | LOCAL_CPPFLAGS += -DANDROID 38 | LOCAL_SHARED_LIBRARIES:=libc 39 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 40 | include $(BUILD_EXECUTABLE) 41 | 42 | include $(CLEAR_VARS) 43 | 44 | LOCAL_MODULE_TAGS := eng 45 | LOCAL_MODULE := camera_to_fb2 46 | LOCAL_SRC_FILES := camera_to_fb2.cpp 47 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 48 | LOCAL_SHARED_LIBRARIES := libcutils libc 49 | LOCAL_STATIC_LIBRARIES := libbdhw 50 | include $(BUILD_EXECUTABLE) 51 | 52 | include $(CLEAR_VARS) 53 | 54 | LOCAL_MODULE_TAGS := eng 55 | LOCAL_MODULE := fb2_overlay 56 | LOCAL_SRC_FILES := fb2_overlay.cpp 57 | LOCAL_CPPFLAGS += -DOVERLAY_MODULETEST 58 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 59 | LOCAL_SHARED_LIBRARIES := libcutils libc 60 | LOCAL_STATIC_LIBRARIES := libbdhw 61 | include $(BUILD_EXECUTABLE) 62 | 63 | include $(CLEAR_VARS) 64 | 65 | LOCAL_MODULE_TAGS := eng 66 | LOCAL_MODULE := ov5640 67 | LOCAL_MODULE_CLASS := ETC 68 | LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/firmware 69 | LOCAL_SRC_FILES := $(LOCAL_MODULE) 70 | include $(BUILD_PREBUILT) 71 | 72 | include $(CLEAR_VARS) 73 | 74 | LOCAL_MODULE_TAGS := eng 75 | LOCAL_MODULE := flipper 76 | LOCAL_SRC_FILES := flipper.cpp 77 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 78 | LOCAL_SHARED_LIBRARIES := libcutils libc 79 | LOCAL_STATIC_LIBRARIES := libbdhw 80 | include $(BUILD_EXECUTABLE) 81 | 82 | include $(CLEAR_VARS) 83 | 84 | LOCAL_MODULE_TAGS := eng 85 | LOCAL_MODULE := fbSet 86 | LOCAL_SRC_FILES := fbSet.cpp 87 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 88 | LOCAL_SHARED_LIBRARIES := libcutils libc 89 | LOCAL_STATIC_LIBRARIES := libbdhw 90 | include $(BUILD_EXECUTABLE) 91 | 92 | include $(CLEAR_VARS) 93 | 94 | LOCAL_MODULE_TAGS := eng 95 | LOCAL_MODULE := physMem 96 | LOCAL_SRC_FILES := physMem.cpp 97 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 98 | LOCAL_SHARED_LIBRARIES := libcutils libc 99 | LOCAL_STATIC_LIBRARIES := libbdhw 100 | LOCAL_CPPFLAGS += -DSTANDALONE=1 101 | include $(BUILD_EXECUTABLE) 102 | 103 | include $(CLEAR_VARS) 104 | 105 | LOCAL_MODULE_TAGS := eng 106 | LOCAL_MODULE := ipu_bufs_mx53 107 | LOCAL_CPPFLAGS += -DMX53 108 | LOCAL_SRC_FILES := ipu_bufs.cpp physMem.cpp 109 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 110 | LOCAL_SHARED_LIBRARIES := libcutils libc 111 | LOCAL_STATIC_LIBRARIES := libbdhw 112 | include $(BUILD_EXECUTABLE) 113 | 114 | include $(CLEAR_VARS) 115 | 116 | LOCAL_MODULE_TAGS := eng 117 | LOCAL_SRC_FILES:=pmic.cpp 118 | LOCAL_MODULE:=pmic 119 | LOCAL_CPPFLAGS += -DANDROID 120 | LOCAL_SHARED_LIBRARIES:=libc 121 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 122 | include $(BUILD_EXECUTABLE) 123 | 124 | include $(CLEAR_VARS) 125 | 126 | LOCAL_MODULE_TAGS := eng 127 | LOCAL_MODULE := ipu_bufs_mx51 128 | LOCAL_CPPFLAGS += -DMX51 129 | LOCAL_SRC_FILES := ipu_bufs.cpp physMem.cpp 130 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 131 | LOCAL_SHARED_LIBRARIES := libcutils libc 132 | LOCAL_STATIC_LIBRARIES := libbdhw 133 | include $(BUILD_EXECUTABLE) 134 | 135 | include $(CLEAR_VARS) 136 | 137 | LOCAL_MODULE_TAGS := eng 138 | LOCAL_MODULE := inputRead 139 | LOCAL_SRC_FILES := inputRead.cpp 140 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 141 | LOCAL_SHARED_LIBRARIES := libcutils libc 142 | LOCAL_STATIC_LIBRARIES := libbdhw 143 | include $(BUILD_EXECUTABLE) 144 | 145 | include $(CLEAR_VARS) 146 | 147 | LOCAL_MODULE_TAGS := eng 148 | LOCAL_MODULE := battery_test 149 | LOCAL_SRC_FILES := battery_test.c 150 | LOCAL_C_INCLUDES += $(LOCAL_PATH) 151 | LOCAL_SHARED_LIBRARIES := libcutils libm 152 | include $(BUILD_EXECUTABLE) 153 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY : clean showversion 2 | 3 | ARCH := arm-none-linux-gnueabi- 4 | CC := ${ARCH}gcc 5 | CXX := ${ARCH}g++ 6 | LD := ${ARCH}g++ 7 | AR := ${ARCH}ar 8 | RANLIB := ${ARCH}ranlib 9 | STRIP := ${ARCH}strip 10 | CXXFLAGS ?= -I/tftpboot/ltib/usr/include -I${HOME}/linux/include -L/tftpboot/ltib/usr/lib 11 | VERSION := $(shell ./makeVersion.sh) 12 | 13 | showversion: 14 | echo "building version ${VERSION} here" 15 | 16 | INCS := -I/tftpboot/linux-bd/include 17 | 18 | LIBRARY_SRCS := camera.cpp cameraParams.cpp fb2_overlay.cpp fourcc.cpp imx_vpu.cpp imx_mjpeg_encoder.cpp \ 19 | libjpeg_encoder.cpp physMem.cpp hexDump.cpp imx_h264_encoder.cpp v4l_display.cpp 20 | LIBRARY_OBJS := $(addsuffix .o,$(basename ${LIBRARY_SRCS})) 21 | LIBRARY := libimx-camera.a 22 | LIBRARY_REF := -L./ -limx-camera 23 | 24 | ${LIBRARY}: ${LIBRARY_OBJS} 25 | @$(AR) r $(LIBRARY) $(LIBRARY_OBJS) 26 | @$(RANLIB) $(LIBRARY) 27 | 28 | camera_to_fb2: camera_to_fb2.cpp ${LIBRARY} 29 | ${CXX} ${CXXFLAGS} ${INCS} ${DEFS} $< ${LIBRARY_REF} -lvpu -lpthread -o $@ 30 | 31 | camera_to_v4l: camera_to_v4l.cpp ${LIBRARY} 32 | ${CXX} ${CXXFLAGS} ${INCS} ${DEFS} $< ${LIBRARY_REF} -lvpu -ljpeg -lpthread -o $@ 33 | 34 | devregs: devregs.cpp ${LIBRARY} 35 | ${CXX} ${CXXFLAGS} ${INCS} ${DEFS} $< ${LIBRARY_REF} -o $@ 36 | 37 | fb2_overlay: fb2_overlay.cpp ${LIBRARY} 38 | ${CXX} ${CXXFLAGS} -DOVERLAY_MODULETEST ${INCS} ${DEFS} $< ${LIBRARY_REF} -o $@ 39 | 40 | ipu_bufs_mx53: ipu_bufs.cpp ${LIBRARY} 41 | ${CXX} ${CXXFLAGS} -DMX53 ${INCS} ${DEFS} $< ${LIBRARY_REF} -o $@ 42 | 43 | ipu_bufs_mx51: ipu_bufs.cpp ${LIBRARY} 44 | ${CXX} ${CXXFLAGS} -DMX51 ${INCS} ${DEFS} $< ${LIBRARY_REF} -o $@ 45 | 46 | battery_test: battery_test.c 47 | ${CC} ${CFLAGS} ${INCS} ${DEFS} $< -o $@ -lm 48 | 49 | pmic: pmic.cpp 50 | ${CXX} ${CXXFLAGS} ${INCS} ${DEFS} $< -o $@ 51 | 52 | imx_h264_encoder: imx_h264_encoder.cpp ${LIBRARY} 53 | ${CXX} ${CXXFLAGS} -DMODULETEST=1 ${INCS} ${DEFS} $< -lvpu ${LIBRARY_REF} -lavformat -lavcodec -lavutil -lz -lbz2 -lpthread -o $@ 54 | 55 | imx_mpeg4_encoder: imx_mpeg4_encoder.cpp ${LIBRARY} 56 | ${CXX} ${CXXFLAGS} -DMODULETEST=1 ${INCS} ${DEFS} $< -lvpu ${LIBRARY_REF} -lavformat -lavcodec -lavutil -lz -lbz2 -lpthread -o $@ 57 | 58 | EXES := camera_to_fb2 camera_to_v4l devregs 59 | 60 | %.o : %.cpp 61 | @echo "=== compiling:" $@ ${OPT} ${CXXFLAGS} 62 | @${CXX} -c ${CXXFLAGS} ${INCS} ${DEFS} $< -o $@ 63 | 64 | all: ${LIBRARY} ${EXES} 65 | 66 | clean: 67 | rm -f ${LIBRARY} ${EXES} *.o 68 | 69 | -------------------------------------------------------------------------------- /battery_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LTC1960 test program 3 | * 4 | * Copyright (c) 2011 EMAC Inc. 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License. 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #ifndef ANDROID 24 | #include 25 | #endif 26 | #include "spidev.h" 27 | 28 | #define CHARGE_BAT1 0x80 29 | #define CHARGE_BAT2 0x40 30 | #define CHARGE_CMD 0x0E 31 | 32 | #define POWERPATH_CMD 0x06 33 | #define POWER_BY_DC 0x20 34 | #define POWER_BY_BAT2 0x40 35 | #define POWER_BY_BAT1 0x80 36 | 37 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) 38 | 39 | static void pabort(const char *s) 40 | { 41 | perror(s); 42 | abort(); 43 | } 44 | 45 | static const char * device = "/dev/spidev2.1"; 46 | static uint8_t mode; 47 | static uint8_t bits = 8; 48 | static uint32_t speed = 100000; 49 | static uint16_t delay = 0; 50 | 51 | int battery_sel = 0; 52 | static struct itimerval tout_val; 53 | 54 | int fd; 55 | 56 | static void status() 57 | { 58 | int ret; 59 | uint8_t tx[2]; 60 | uint8_t rx[2]; 61 | 62 | tx[0] = 0x04; 63 | tx[1] = 0x05; 64 | 65 | struct spi_ioc_transfer tr = { 66 | .tx_buf = (unsigned long)tx, 67 | .rx_buf = (unsigned long)rx, 68 | .len = ARRAY_SIZE(tx), 69 | .delay_usecs = delay, 70 | .speed_hz = speed, 71 | .bits_per_word = bits, 72 | }; 73 | 74 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 75 | if (ret < 1) 76 | pabort("can't send spi message"); 77 | 78 | printf("Charging = %x\n", (rx[1] >> 2) & 1); 79 | printf("Power Fail = %x\n", (rx[1] >> 3) & 1); 80 | printf("DCDIV = %x\n", (rx[1] >> 4) & 1); 81 | printf("Low Power = %x\n", (rx[1] >> 5) & 1); 82 | printf("Fault = %x\n", (rx[1] >> 6) & 1); 83 | 84 | 85 | } 86 | 87 | static void charge(int battery) 88 | { 89 | int ret; 90 | 91 | uint8_t tx[1]; 92 | uint8_t rx[1]; 93 | 94 | tx[0] = battery | CHARGE_CMD; 95 | 96 | struct spi_ioc_transfer tr = { 97 | .tx_buf = (unsigned long)tx, 98 | .rx_buf = (unsigned long)rx, 99 | .len = ARRAY_SIZE(tx), 100 | .delay_usecs = delay, 101 | .speed_hz = speed, 102 | .bits_per_word = bits, 103 | }; 104 | 105 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 106 | if (ret < 1) 107 | pabort("can't send spi message"); 108 | 109 | } 110 | 111 | static void voltage_dac(double voltage) 112 | { 113 | int ret; 114 | int vdac; 115 | int i; 116 | 117 | uint8_t tx[2]; 118 | uint8_t rx[2]; 119 | 120 | tx[0] = 0x01; 121 | tx[1] = 0x08; 122 | 123 | 124 | vdac = (int) floor(((voltage-.8)/32.752) * 2047); 125 | 126 | for(i=0;i<10;i++) 127 | { 128 | if(i<7) 129 | tx[0] |= (vdac & (1 << i)) ? (1 << (7-i)) : 0; 130 | else 131 | tx[1] |= (vdac & (1 << i)) ? (1 << (14-i)) : 0; 132 | } 133 | 134 | struct spi_ioc_transfer tr = { 135 | .tx_buf = (unsigned long)tx, 136 | .rx_buf = (unsigned long)rx, 137 | .len = ARRAY_SIZE(tx), 138 | .delay_usecs = delay, 139 | .speed_hz = speed, 140 | .bits_per_word = bits, 141 | }; 142 | 143 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 144 | if (ret < 1) 145 | pabort("can't send spi message"); 146 | 147 | do 148 | { 149 | tx[0] = 0x01; 150 | struct spi_ioc_transfer tr = { 151 | .tx_buf = (unsigned long)tx, 152 | .rx_buf = (unsigned long)rx, 153 | .len = 1, 154 | .delay_usecs = delay, 155 | .speed_hz = speed, 156 | .bits_per_word = bits, 157 | }; 158 | 159 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 160 | if (ret < 1) 161 | pabort("can't send spi message"); 162 | } while(rx[0]==0xFF); 163 | 164 | } 165 | 166 | static void current_dac(double current, int low_current) 167 | { 168 | int ret; 169 | int cdac; 170 | int i; 171 | 172 | uint8_t tx[2]; 173 | uint8_t rx[2]; 174 | 175 | tx[0] = 0x01; 176 | tx[1] = 0x00; 177 | 178 | cdac = (int) (((current)*1023*0.05)/0.1023); 179 | 180 | for(i=0;i<10;i++) 181 | { 182 | if(i<7) 183 | tx[0] |= (cdac & (1 << i)) ? (1 << (7-i)) : 0; 184 | else 185 | tx[1] |= (cdac & (1 << i)) ? (1 << (14-i)) : 0; 186 | } 187 | 188 | tx[1] |= (low_current) ? 0x10 : 0x00; 189 | 190 | struct spi_ioc_transfer tr = { 191 | .tx_buf = (unsigned long)tx, 192 | .rx_buf = (unsigned long)rx, 193 | .len = ARRAY_SIZE(tx), 194 | .delay_usecs = delay, 195 | .speed_hz = speed, 196 | .bits_per_word = bits, 197 | }; 198 | 199 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 200 | if (ret < 1) 201 | pabort("can't send spi message"); 202 | 203 | do 204 | { 205 | tx[0] = 0x01; 206 | struct spi_ioc_transfer tr = { 207 | .tx_buf = (unsigned long)tx, 208 | .rx_buf = (unsigned long)rx, 209 | .len = 1, 210 | .delay_usecs = delay, 211 | .speed_hz = speed, 212 | .bits_per_word = bits, 213 | }; 214 | 215 | ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); 216 | if (ret < 1) 217 | pabort("can't send spi message"); 218 | } while(rx[0]==0xFF); 219 | 220 | } 221 | 222 | void charge_timer(int i) 223 | { 224 | if(battery_sel) charge(battery_sel); 225 | 226 | signal(SIGALRM, charge_timer); 227 | } 228 | 229 | void init_timer() 230 | { 231 | tout_val.it_interval.tv_sec = 1; /* Next Value in seconds */ 232 | tout_val.it_interval.tv_usec = 1; /* Next Value in microseconds */ 233 | tout_val.it_value.tv_sec = 1; /* Current Value in seconds */ 234 | tout_val.it_value.tv_usec = 1; /* Current Value in microseconds */ 235 | setitimer(ITIMER_REAL, &tout_val, 0); 236 | signal(SIGALRM, charge_timer); 237 | } 238 | 239 | int main(int argc, char *argv[]) 240 | { 241 | int ret = 0; 242 | int done = 0; 243 | int low_current = 0; 244 | char key; 245 | double voltage, current; 246 | 247 | fd = open(device, O_RDWR); 248 | if (fd < 0) 249 | pabort("Cannot open device"); 250 | 251 | ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); 252 | if (ret == -1) 253 | pabort("Cannot set bits per word"); 254 | 255 | ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); 256 | if (ret == -1) 257 | pabort("Cannot set max speed hz"); 258 | 259 | 260 | init_timer(); 261 | 262 | printf("LTC1960 Battery Charger Demo\n\n"); 263 | 264 | current = 2.0; 265 | voltage = 12.8; 266 | 267 | voltage_dac(voltage); 268 | current_dac(current, low_current); 269 | 270 | while(!done) 271 | { 272 | 273 | status(); 274 | 275 | printf("\n"); 276 | 277 | printf("Battery 1 is %s.\n", (battery_sel==CHARGE_BAT1) ? "charging" : "not charging"); 278 | printf("Battery 2 is %s.\n", (battery_sel==CHARGE_BAT2) ? "charging" : "not charging"); 279 | printf("Current = %lfA\n",current); 280 | printf("Voltage = %lfV\n",voltage); 281 | printf("Low Current Mode %s.\n", (low_current) ? "ON" : "OFF"); 282 | 283 | printf("\n"); 284 | 285 | printf("1: Set battery voltage.\n"); 286 | printf("2: Set battery current.\n"); 287 | printf("3: Charge battery 1. \n"); 288 | printf("4: Charge battery 2. \n"); 289 | printf("5: Toggle Low Current Mode. \n"); 290 | printf("6: Stop Charging. \n"); 291 | printf("7: Print smart battery info.\n"); 292 | printf("q: Quit Program\n"); 293 | 294 | printf("\nInput: "); 295 | 296 | do 297 | { 298 | scanf("%c", &key); 299 | } while(key == '\n'); 300 | 301 | printf("\n\n"); 302 | switch(key) 303 | { 304 | case '1': printf("Voltage = "); 305 | scanf("%lf", &voltage); 306 | voltage_dac(voltage); 307 | break; 308 | case '2': printf("Current = "); 309 | scanf("%lf", ¤t); 310 | current_dac(current, low_current); 311 | break; 312 | case '3': battery_sel = CHARGE_BAT1; 313 | charge(battery_sel); 314 | break; 315 | case '4': battery_sel = CHARGE_BAT2; 316 | charge(battery_sel); 317 | break; 318 | case '5': low_current ^=1; 319 | current_dac(current, low_current); 320 | break; 321 | case '6': battery_sel = 0; 322 | sleep(1); 323 | break; 324 | case '7': system("cat /sys/class/power_supply/battery/uevent"); 325 | break; 326 | case 'q': done = 1; 327 | break; 328 | default: continue; 329 | } 330 | } 331 | 332 | close(fd); 333 | 334 | return ret; 335 | } 336 | -------------------------------------------------------------------------------- /camera.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module camera.cpp 3 | * 4 | * This module defines the methods of the camera_t class 5 | * as declared in camera.h 6 | * 7 | * 8 | * Change History : 9 | * 10 | * $Log$ 11 | * 12 | * Copyright Boundary Devices, Inc. 2010 13 | */ 14 | 15 | 16 | #include "camera.h" 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | //#include 30 | #include "fourcc.h" 31 | 32 | // #define DEBUGPRINT 33 | #include "debugPrint.h" 34 | 35 | static int xioctl(int fd, int request, void *arg) 36 | { 37 | int r; 38 | // printf("%s: request %x\n", __func__, request); 39 | // fflush (stdout); 40 | 41 | do { 42 | r = ioctl (fd, request, arg); 43 | } while (-1 == r && EINTR == errno); 44 | // printf("%s: result %x\n", __func__, r); 45 | // fflush (stdout); 46 | // usleep(500); 47 | // printf("%s: return %d\n", __func__, r); 48 | return r; 49 | } 50 | 51 | camera_t::camera_t 52 | ( char const *devName, 53 | unsigned width, 54 | unsigned height, 55 | unsigned fps, 56 | unsigned pixelformat, 57 | rotation_e rotation ) 58 | : fd_( -1 ) 59 | , w_(width) 60 | , h_(height) 61 | , v4l_buffers_(0) 62 | , buffers_(0) 63 | , n_buffers_(0) 64 | , buffer_length_(0) 65 | , numRead_(0) 66 | , frame_drops_(0) 67 | , lastRead_(0xffffffff) 68 | { 69 | struct stat st; 70 | 71 | if (-1 == stat (devName, &st)) { 72 | ERRMSG( "Cannot identify '%s': %d, %s\n", 73 | devName, errno, strerror (errno)); 74 | return ; 75 | } 76 | 77 | if (!S_ISCHR (st.st_mode)) { 78 | ERRMSG( "%s is no device\n", devName ); 79 | return ; 80 | } 81 | 82 | fd_ = open (devName, O_RDWR /* required */ | O_NONBLOCK, 0); 83 | 84 | if (0 > fd_) { 85 | ERRMSG( "Cannot open '%s': %d, %s\n", 86 | devName, errno, strerror (errno)); 87 | return ; 88 | } 89 | 90 | struct v4l2_capability cap; 91 | if (-1 == xioctl (fd_, VIDIOC_QUERYCAP, &cap)) { 92 | if (EINVAL == errno) { 93 | ERRMSG( "%s is no V4L2 device\n", devName); 94 | } 95 | else { 96 | ERRMSG( "VIDIOC_QUERYCAP:%m"); 97 | } 98 | goto bail ; 99 | } 100 | 101 | if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { 102 | ERRMSG( "%s is no video capture device\n", devName); 103 | goto bail ; 104 | } 105 | if (!(cap.capabilities & V4L2_CAP_STREAMING)) { 106 | ERRMSG( "%s does not support streaming i/o\n", devName); 107 | goto bail ; 108 | } 109 | 110 | int input ; 111 | int r; 112 | 113 | input = isYUV(pixelformat) ? 0 : 1 ; 114 | 115 | /* Select video input, video standard and tune here. */ 116 | r = xioctl (fd_, VIDIOC_S_INPUT, &input); 117 | if (r) { 118 | ERRMSG( "%s does not support input#%i, ret=0x%x\n", devName, input, r); 119 | // goto bail ; 120 | } 121 | 122 | struct v4l2_cropcap cropcap ; memset(&cropcap,0,sizeof(cropcap)); 123 | cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 124 | 125 | if (0 == xioctl (fd_, VIDIOC_CROPCAP, &cropcap)) { 126 | struct v4l2_crop crop ; memset(&crop,0,sizeof(crop)); 127 | crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 128 | crop.c = cropcap.defrect; /* reset to default */ 129 | 130 | if (-1 == xioctl (fd_, VIDIOC_S_CROP, &crop)) { 131 | switch (errno) { 132 | case EINVAL: 133 | /* Cropping not supported. */ 134 | break; 135 | default: 136 | /* Errors ignored. */ 137 | break; 138 | } 139 | } 140 | } 141 | else { 142 | /* Errors ignored. */ 143 | } 144 | 145 | memset(&fmt_,0,sizeof(fmt_)); 146 | 147 | fmt_.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 148 | fmt_.fmt.pix.width = width ; 149 | fmt_.fmt.pix.height = height ; 150 | fmt_.fmt.pix.pixelformat = pixelformat ; 151 | 152 | if (-1 == xioctl (fd_, VIDIOC_S_FMT, &fmt_)) { 153 | perror("VIDIOC_S_FMT"); 154 | goto bail ; 155 | } 156 | 157 | ERRMSG("%s: set pixel format %s, sizeimage == %u\n", __func__, fourcc_str(fmt_.fmt.pix.pixelformat), fmt_.fmt.pix.sizeimage); 158 | 159 | if ( (width != fmt_.fmt.pix.width) 160 | || 161 | (height != fmt_.fmt.pix.height) ) { 162 | ERRMSG( "%ux%u not supported: %ux%u\n", width, height,fmt_.fmt.pix.width, fmt_.fmt.pix.height); 163 | goto bail ; 164 | } 165 | 166 | ERRMSG("%s: size: %ux%u\n", __func__, fmt_.fmt.pix.width, fmt_.fmt.pix.height); 167 | 168 | /* 169 | struct v4l2_control rotate_control ; memset(&rotate_control,0,sizeof(rotate_control)); 170 | rotate_control.id = V4L2_CID_MXC_ROT ; 171 | rotate_control.value = rotation ; 172 | if ( 0 > xioctl(fd_, VIDIOC_S_CTRL, &rotate_control) ) { 173 | perror( "VIDIOC_S_CTRL(rotation)"); 174 | goto bail ; 175 | } 176 | */ 177 | struct v4l2_streamparm stream_parm; 178 | 179 | if (-1 == xioctl (fd_, VIDIOC_G_PARM, &stream_parm)) { 180 | perror("VIDIOC_G_PARM"); 181 | // goto bail ; 182 | } 183 | 184 | stream_parm.parm.capture.timeperframe.numerator = 1; 185 | stream_parm.parm.capture.timeperframe.denominator = (fps? fps : 30); 186 | if (-1 == xioctl (fd_, VIDIOC_S_PARM, &stream_parm)) 187 | perror ("VIDIOC_S_PARM"); 188 | 189 | struct v4l2_requestbuffers req ; memset(&req,0,sizeof(req)); 190 | 191 | req.count = 5; 192 | req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 193 | req.memory = V4L2_MEMORY_MMAP; 194 | 195 | if (-1 == xioctl (fd_, VIDIOC_REQBUFS, &req)) { 196 | if (EINVAL == errno) { 197 | ERRMSG( "%s does not support memory mapping\n", devName); 198 | } 199 | else { 200 | perror("VIDIOC_REQBUFS"); 201 | } 202 | goto bail ; 203 | } 204 | 205 | if (req.count < 2) { 206 | ERRMSG( "Insufficient buffer memory on %s\n", devName); 207 | goto bail ; 208 | } 209 | 210 | v4l_buffers_ = (struct v4l2_buffer *)calloc (req.count, sizeof(v4l_buffers_[0])); 211 | if (!v4l_buffers_) { 212 | ERRMSG( "Out of memory\n"); 213 | goto bail ; 214 | } 215 | 216 | buffers_ = (unsigned char **)calloc (req.count, sizeof (buffers_[0])); 217 | 218 | if (!buffers_) { 219 | ERRMSG( "Out of memory\n"); 220 | goto bail ; 221 | } 222 | 223 | for (n_buffers_ = 0; n_buffers_ < req.count; ++n_buffers_) { 224 | struct v4l2_buffer &buf = v4l_buffers_[n_buffers_]; 225 | memset(&buf,0,sizeof(buf)); 226 | 227 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 228 | buf.memory = V4L2_MEMORY_MMAP; 229 | buf.index = n_buffers_ ; 230 | 231 | if (-1 == xioctl (fd_, VIDIOC_QUERYBUF, &buf)) { 232 | perror ("VIDIOC_QUERYBUF"); 233 | goto bail; 234 | } 235 | debugPrint("%s: buffer lengths %u/%u\n", __func__, buffer_length_,buf.length); 236 | assert((0 == buffer_length_)||(buf.length == buffer_length_)); // only handle single buffer size 237 | buffer_length_ = buf.length; 238 | buffers_[n_buffers_] = (unsigned char *) 239 | mmap (NULL /* start anywhere */, 240 | buf.length, 241 | PROT_READ /* required */, 242 | MAP_SHARED /* recommended */, 243 | fd_, buf.m.offset); 244 | 245 | if (MAP_FAILED == buffers_[n_buffers_]) { 246 | perror("mmap"); 247 | goto bail ; 248 | } 249 | 250 | if (fmt_.fmt.pix.sizeimage > buf.length) 251 | ERRMSG("camera_imgsize=%x but buf.length=%x\n", fmt_.fmt.pix.sizeimage, buf.length); 252 | } 253 | pfd_.fd = fd_ ; 254 | pfd_.events = POLLIN ; 255 | 256 | return ; 257 | 258 | bail: 259 | close(fd_); fd_ = -1 ; 260 | 261 | } 262 | 263 | camera_t::~camera_t(void) { 264 | if ( buffers_ ) { 265 | while ( 0 < n_buffers_ ) { 266 | munmap(buffers_[n_buffers_-1],buffer_length_); 267 | --n_buffers_ ; 268 | } 269 | free(buffers_); 270 | buffers_ = 0 ; 271 | } 272 | if (v4l_buffers_) { 273 | free(v4l_buffers_); 274 | v4l_buffers_ = 0 ; 275 | } 276 | if (isOpen()) { 277 | close(fd_); 278 | fd_ = -1 ; 279 | } 280 | } 281 | 282 | // capture interface 283 | bool camera_t::startCapture(void) 284 | { 285 | if ( !isOpen() ) 286 | return false ; 287 | 288 | unsigned int i; 289 | 290 | for (i = 0; i < n_buffers_; ++i) { 291 | struct v4l2_buffer buf ; memset(&buf,0,sizeof(buf)); 292 | 293 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 294 | buf.memory = V4L2_MEMORY_MMAP; 295 | buf.index = i; 296 | buf.m.offset = 0; 297 | 298 | if (-1 == xioctl (fd_, VIDIOC_QUERYBUF, &buf)) { 299 | perror ("VIDIOC_QUERYBUF"); 300 | return false; 301 | } 302 | if (-1 == xioctl (fd_, VIDIOC_QBUF, &buf)) { 303 | perror ("VIDIOC_QBUF"); 304 | return false ; 305 | } 306 | else { 307 | debugPrint( "queued buffer %u\n", i ); 308 | } 309 | } 310 | 311 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 312 | 313 | if (-1 == xioctl (fd_, VIDIOC_STREAMON, &type)) { 314 | perror ("VIDIOC_STREAMON"); 315 | return false ; 316 | } 317 | else { 318 | debugPrint( "streaming started\n" ); 319 | } 320 | return true ; 321 | } 322 | 323 | bool camera_t::grabFrame(void const *&data,int &index) { 324 | 325 | int timeout = 100 ; // 1/10 second max 326 | index = -1 ; 327 | while (1) { 328 | int numReady = poll(&pfd_, 1, timeout); 329 | if ( 0 < numReady ) { 330 | debugPrint( "%s: %d fds ready\n", __func__, numReady ); 331 | timeout = 0 ; 332 | struct v4l2_buffer buf ; 333 | memset(&buf,0,sizeof(buf)); 334 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 335 | buf.memory = V4L2_MEMORY_MMAP; 336 | int rv ; 337 | if (0 == (rv = xioctl (fd_, VIDIOC_DQBUF, &buf))) { 338 | ++ numRead_ ; 339 | if (0 != (rv = xioctl (fd_, VIDIOC_QUERYBUF, &buf))) { 340 | fprintf(stderr, "QUERYBUF:%d:%m\n", rv); 341 | } 342 | if (0 <= index) { 343 | ERRMSG("camera frame drop\n"); 344 | ++frame_drops_ ; 345 | returnFrame(data,index); 346 | } 347 | assert (buf.index < n_buffers_); 348 | data = buffers_[buf.index]; 349 | index = buf.index ; 350 | debugPrint( "DQ index %u: %p\n", index, data ); 351 | lastRead_ = index ; 352 | break; 353 | } 354 | else if ((errno != EAGAIN)&&(errno != EINTR)) { 355 | ERRMSG("VIDIOC_DQBUF"); 356 | } 357 | else { 358 | if (EAGAIN != errno) 359 | ERRMSG("%s: rv %d, errno %d\n", __func__, rv, errno); 360 | } 361 | } 362 | break; // continue from middle 363 | } 364 | debugPrint( "%s: returning %d\n", __func__,(0 <= index)); 365 | return (0 <= index); 366 | } 367 | 368 | void camera_t::returnFrame(void const *data, int index) { 369 | struct v4l2_buffer buf ; 370 | memset(&buf,0,sizeof(buf)); 371 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE ; 372 | buf.memory = V4L2_MEMORY_MMAP; 373 | buf.index = index ; 374 | if (0 != xioctl (fd_, VIDIOC_QBUF, &buf)) 375 | perror("VIDIOC_QBUF"); 376 | else { 377 | // debugPrint( "returned frame %p/%d\n", data, index ); 378 | } 379 | } 380 | 381 | bool camera_t::stopCapture(void){ 382 | if ( !isOpen() ) 383 | return false ; 384 | 385 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 386 | if (-1 == xioctl (fd_, VIDIOC_STREAMOFF, &type)) { 387 | perror ("VIDIOC_STREAMOFF"); 388 | return false ; 389 | } 390 | else { 391 | debugPrint( "capture stopped\n" ); 392 | } 393 | 394 | return true ; 395 | } 396 | 397 | #ifdef STANDALONE_CAMERA 398 | 399 | #include 400 | #include "tickMs.h" 401 | #include 402 | #include "cameraParams.h" 403 | #include 404 | 405 | bool volatile die = false ; 406 | 407 | static void ctrlcHandler( int signo ) 408 | { 409 | printf( "(%d)\r\n", signo ); 410 | die = true ; 411 | } 412 | 413 | int main(int argc, char const **argv) { 414 | int rval = -1 ; 415 | cameraParams_t params(argc,argv); 416 | long long start = tickMs(); 417 | signal( SIGINT, ctrlcHandler ); 418 | camera_t camera(params.getCameraDeviceName(), 419 | params.getCameraWidth(), 420 | params.getCameraHeight(), 421 | params.getCameraFPS(), 422 | params.getCameraFourcc(), 423 | params.getCameraRotation()); 424 | long long end = tickMs(); 425 | if ( camera.isOpen() ) { 426 | printf( "camera opened in %llu ms\n",end-start); 427 | start = tickMs(); 428 | if ( camera.startCapture() ) { 429 | end = tickMs(); 430 | printf( "started capture in %llu ms\n", end-start); 431 | 432 | long long startCapture = end ; 433 | long long maxGrab = 0, maxRelease = 0 ; 434 | unsigned numFrames = 0 ; 435 | for ( int i = 0 ; !die && ((0 > params.getIterations()) || (i < params.getIterations())) ; i++ ) { 436 | start = tickMs(); 437 | void const *data ; 438 | int index ; 439 | while ( !(die || camera.grabFrame(data,index)) ) 440 | ; 441 | end = tickMs(); 442 | if(die) 443 | break; 444 | ++numFrames ; 445 | long long elapsed = end-start ; 446 | debugPrint( "frame %p:%d, %llu ms\n", data, index, elapsed ); 447 | if ( elapsed > maxGrab ) 448 | maxGrab = elapsed ; 449 | if(numFrames == params.getSaveFrameNumber()){ 450 | char const outFileName[] = { 451 | "/tmp/camera.out" 452 | }; 453 | FILE *fOut = fopen(outFileName, "wb"); 454 | if(fOut){ 455 | fwrite(data,camera.imgSize(),1,fOut); 456 | fclose(fOut); 457 | printf( "saved frame to %s\n", outFileName); 458 | } 459 | else 460 | perror(outFileName); 461 | } 462 | start = tickMs(); 463 | camera.returnFrame(data,index); 464 | end = tickMs(); 465 | elapsed = end-start ; 466 | if ( elapsed > maxRelease ) 467 | maxRelease = elapsed ; 468 | } 469 | 470 | long long endCapture = start = tickMs(); 471 | if ( camera.stopCapture() ) { 472 | end=tickMs(); 473 | printf( "closed capture in %llu ms\n", end-start); 474 | printf( "maxGrab: %llu ms, maxRelease: %llu ms\n", maxGrab, maxRelease ); 475 | unsigned long elapsed = (endCapture-startCapture); 476 | printf( "%u frames in %lu ms (%u fps)\n", numFrames, elapsed, (numFrames*1000)/elapsed ); 477 | rval = 0 ; 478 | } 479 | else 480 | ERRMSG( "Error stopping capture\n" ); 481 | } 482 | else 483 | ERRMSG( "Error starting capture\n" ); 484 | } 485 | 486 | return rval ; 487 | } 488 | 489 | #endif 490 | -------------------------------------------------------------------------------- /camera.h: -------------------------------------------------------------------------------- 1 | #ifndef __CAMERA_H__ 2 | #define __CAMERA_H__ "$Id$" 3 | 4 | /* 5 | * camera.h 6 | * 7 | * This header file declares the camera_t class, which is 8 | * a thin wrapper around an mmap'd V4L2 device that returns 9 | * frames to the caller for processing. 10 | * 11 | * Note that this class sets the camera file descriptor to 12 | * non-blocking. Use poll() or select() to wait for a frame. 13 | * 14 | * Change History : 15 | * 16 | * $Log$ 17 | * 18 | * 19 | * Copyright Boundary Devices, Inc. 2010 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | class camera_t { 26 | public: 27 | enum rotation_e { 28 | ROTATE_NONE = 0, 29 | FLIP_VERTICAL = 1, 30 | FLIP_HORIZONTAL = 2, 31 | FLIP_BOTH = 3, 32 | ROTATE_90_RIGHT = 4, 33 | ROTATE_90_LEFT = 7 34 | }; 35 | camera_t( char const *devName, 36 | unsigned width, 37 | unsigned height, 38 | unsigned fps, 39 | unsigned pixelformat, 40 | rotation_e rotation = ROTATE_NONE ); 41 | ~camera_t(void); 42 | 43 | bool isOpen(void) const { return 0 <= fd_ ;} 44 | int getFd(void) const { return fd_ ;} 45 | 46 | unsigned getWidth(void) const { return w_ ;} 47 | unsigned getHeight(void) const { return h_ ;} 48 | unsigned stride(void) const { return fmt_.fmt.pix.bytesperline ;} 49 | unsigned imgSize(void) const { return fmt_.fmt.pix.sizeimage ;} 50 | unsigned numBuffers(void) const { return n_buffers_ ; } 51 | struct v4l2_buffer *v4l2_Buffers(void) const { return v4l_buffers_ ;} 52 | unsigned char **getBuffers(void) const { return buffers_ ; } 53 | 54 | // capture interface 55 | bool startCapture(void); 56 | 57 | // pull frames with this method 58 | bool grabFrame(void const *&data,int &index); 59 | 60 | // return them with this method 61 | void returnFrame(void const *data, int index); 62 | 63 | bool stopCapture(void); 64 | 65 | unsigned numRead(void) const { return numRead_ ;} 66 | unsigned numDropped(void) const { return frame_drops_ ;} 67 | unsigned lastRead(void) const { return lastRead_ ;} 68 | private: 69 | int fd_ ; 70 | unsigned const w_ ; 71 | unsigned const h_ ; 72 | struct pollfd pfd_ ; 73 | struct v4l2_format fmt_ ; 74 | struct v4l2_buffer *v4l_buffers_ ; 75 | unsigned char **buffers_ ; 76 | unsigned n_buffers_ ; 77 | unsigned buffer_length_ ; 78 | unsigned numRead_ ; 79 | unsigned frame_drops_ ; 80 | unsigned lastRead_ ; 81 | }; 82 | 83 | #endif 84 | 85 | -------------------------------------------------------------------------------- /cameraParams.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module cameraParams.cpp 3 | * 4 | * This module defines the methods of the cameraParams_t class 5 | * as declared in cameraParams.h 6 | * 7 | * Copyright Boundary Devices, Inc. 2010 8 | */ 9 | 10 | #include "cameraParams.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "fourcc.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | static bool parseIP(char const *ip_and_port, unsigned &targetAddr, unsigned short &targetPort) 22 | { 23 | printf( "parsing IP and port: %s\n", ip_and_port); 24 | char const *colon = strchr(ip_and_port,':'); 25 | char ip_address[256]; 26 | if(colon &&((colon-ip_and_port)= color_key ; } 43 | 44 | int getSaveFrameNumber(void) const { return saveFrame ; } 45 | int getIterations(void) const { return iterations ; } 46 | 47 | // returns 0 for no broadcast 48 | unsigned getBroadcastAddr(void) const { return broadcastAddr ; } 49 | unsigned short getBroadcastPort(void) const { return broadcastPort ; } 50 | 51 | void dump(void) const ; 52 | private: 53 | unsigned inwidth ; 54 | unsigned inheight ; 55 | camera_t::rotation_e rotation ; 56 | unsigned fps ; 57 | unsigned fourcc ; 58 | unsigned gopSize ; 59 | unsigned x ; 60 | unsigned y ; 61 | unsigned outwidth ; 62 | unsigned outheight ; 63 | unsigned transparency ; 64 | unsigned color_key ; 65 | char const *cameraDevName ; 66 | char const *previewDevName ; 67 | int saveFrame ; 68 | int iterations ; 69 | unsigned broadcastAddr ; 70 | unsigned short broadcastPort ; 71 | }; 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /clean_devregs.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | $value['stopbit']) { 46 | $tmp = $value['startbit']; 47 | $value['startbit'] = $value['stopbit']; 48 | $value['stopbit'] = $tmp; 49 | } 50 | $value['type'] = $FIELD ; 51 | } else 52 | print( "invalid bitfield on line $line\n" ); 53 | } else { 54 | print ("field $line missing bitfield\n"); 55 | } 56 | } else if (('_' == $line[0]) || (('A' <= $line[0])&&('Z' >= $line[0]))) { 57 | $parts = $value['parts'] = sscanf($line,"%s %s"); 58 | if (2 == count($parts)) { 59 | $value['name'] = $parts[0]; 60 | $address = $parts[1]; 61 | $parts = explode('.',$address); 62 | if (2 > count($parts)) 63 | $parts[] = 'L' ; 64 | $value['address'] = strtoupper($parts[0]); 65 | $value['width'] = $parts[1]; 66 | $value['type'] = $REGISTER ; 67 | } 68 | else 69 | print ("Invalid field: $line\n"); 70 | } 71 | return $value['type']; 72 | } 73 | 74 | $fields_by_name = array(); 75 | $field_dups = 0 ; 76 | $registers_by_address = array(); 77 | $register_dups = 0 ; 78 | $fieldsets = array(); 79 | $fieldset_usage = array(); 80 | $fieldsets_by_hash = array(); 81 | $fieldset_dups = 0 ; 82 | 83 | function dedupe_field($field) { 84 | global $fields_by_name ; 85 | global $field_dups ; 86 | $name = $field['name']; 87 | $start = $field['startbit']; 88 | $stop = $field['stopbit']; 89 | $fields = isset($fields_by_name[$name]) ? $fields_by_name[$name] : null ; 90 | if (is_array($fields)) { 91 | foreach ($fields as $f) { 92 | if (($start == $f['start'])&&($stop==$f['stop'])) { 93 | // print('matched:'); print_r($f); 94 | $field_dups++ ; 95 | return $f ; 96 | } 97 | } 98 | } 99 | $rval = array('name'=>$name,'start'=>$start,'stop'=>$stop); 100 | $fields_by_name[$name][] = $rval ; 101 | return $rval ; 102 | } 103 | 104 | function dedupe_register($reg) { 105 | global $registers_by_address ; 106 | global $register_dups ; 107 | $name = $reg['name']; 108 | $addr = $reg['address']; 109 | $width = $reg['width']; 110 | $regs = isset($registers_by_address[$addr]) ? $registers_by_address[$addr] : null ; 111 | if (is_array($regs)) { 112 | foreach ($regs as &$r) { 113 | if ($r['name'] == $name) { 114 | printf( "matched 0x%x:$name\n", $addr); 115 | $register_dups++ ; 116 | return $r ; 117 | } 118 | } 119 | } else 120 | $registers_by_address[$addr] = array(); 121 | $idx = count($registers_by_address[$addr]); 122 | $registers_by_address[$addr][] = array('name'=>$name,'address'=>$addr,'width'=>$width); 123 | return $registers_by_address[$addr][$idx]; 124 | } 125 | 126 | function field_sum($field_sum,$field){ 127 | foreach ($field as $value) { 128 | $field_sum += crc32($value); 129 | } 130 | return $field_sum ; 131 | } 132 | 133 | function dedupe_fieldset(&$fs,$regname) { 134 | global $fieldsets_by_hash ; 135 | global $fieldsets ; 136 | global $fieldset_usage ; 137 | global $fieldset_dups ; 138 | $hash = array_reduce($fs,'field_sum',0); 139 | $fs['hash'] = $hash ; 140 | if (isset($fieldsets_by_hash[$hash])) { 141 | $fsets =& $fieldsets_by_hash[$hash]; 142 | foreach($fsets as $fsetidx) { 143 | $fset =& $fieldsets[$fsetidx]; 144 | if ($fset == $fs) { 145 | // print( "matched fieldset $hash:".count($fsets).":"); print_r($fs); 146 | $fieldset_dups++ ; 147 | $fieldset_usage[$fsetidx]++ ; 148 | return $fsetidx ; 149 | } 150 | } 151 | } 152 | else { 153 | $fieldsets_by_hash[$hash] = array(); 154 | } 155 | $idx = count($fieldsets); 156 | $fieldsets[] = $fs ; 157 | $fieldset_usage[] = 1 ; 158 | $fieldsets_by_hash[$hash][] = $idx ; 159 | return $idx ; 160 | } 161 | 162 | function add_fields($reg,$fs) { 163 | global $registers_by_address ; 164 | global $register_dups ; 165 | $name = $reg['name']; 166 | $addr = $reg['address']; 167 | if (isset($registers_by_address[$addr])) { 168 | $regs =& $registers_by_address[$addr]; 169 | foreach ($regs as &$r) { 170 | if ($r['name'] == $name) { 171 | $r['fields'] = $fs ; 172 | return ; 173 | } 174 | } 175 | } else 176 | print ("Error finding reg $reg[name].$reg[address]\n" ); 177 | } 178 | 179 | if (isset($argc) && ($argc > 1)) { 180 | $fIn = file($argv[1]); 181 | print("$argv[1]: ".count($fIn)." lines\n"); 182 | $numComments = 0 ; 183 | $lineTypes = array($COMMENT=>0,$REGISTER=>0,$FIELD=>0,$PARSEERR=>0); 184 | $prevreg = null ; 185 | $fieldset = array(); 186 | foreach($fIn as $line) { 187 | $value= array(); 188 | $type = parseLine($line,$value); 189 | $lineTypes[$type]++ ; 190 | if ($REGISTER == $type) { 191 | if (0 < count($fieldset)) { 192 | if (null !== $prevreg) { 193 | $fieldset =& dedupe_fieldset($fieldset,$prevreg['name']); 194 | if (isset($prevreg['fields'])) { 195 | print( "register $prevreg[name] has fields\n"); 196 | } 197 | add_fields($prevreg,$fieldset); 198 | $prevreg['fields'] =& $fieldset ; 199 | // print('prevreg: '); print_r($prevreg); 200 | } else 201 | print ("missing register at end of fieldset\n"); 202 | $fieldset = array(); 203 | } 204 | $prevreg =& dedupe_register($value); 205 | // print_r($value); 206 | } else if ($FIELD == $type) { 207 | $field =& dedupe_field($value); 208 | $fieldset[] = $field ; 209 | // print( "line $line: "); print_r($field); 210 | } else { 211 | } 212 | } 213 | if ((0 < count($fieldset)) && isset($prevreg)) { 214 | $fieldset =& dedupe_fieldset($fieldset,$prevreg['name']); 215 | if (isset($prevreg['fields'])) { 216 | print( "register $prevreg[name] has fields\n"); 217 | } 218 | add_fields($prevreg,$fieldset); 219 | $prevreg['fields'] =& $fieldset ; 220 | } 221 | print_r($lineTypes); 222 | print("" .($lineTypes[0]+$lineTypes[1]+$lineTypes[2]+$lineTypes[3])." lines\n"); 223 | print( "matched ".count($fields_by_name)." fields, $field_dups duplicates\n"); 224 | print( "matched ".count($registers_by_address)." registers, $register_dups duplicates\n"); 225 | print( "matched ".count($fieldsets_by_hash). " fieldsets, $fieldset_dups duplicates\n"); 226 | for ($i = 0 ; $i < count($fieldsets); $i++) { 227 | $fields = $fieldsets[$i]; 228 | $usage = $fieldset_usage[$i]; 229 | if (1 < $usage) { 230 | print("/fs$i\t\t#usage $fieldset_usage[$i]\n"); 231 | foreach ($fields as $idx => $field) { 232 | if (is_int($idx)) { 233 | $start = $field['start']; 234 | $stop = $field['stop']; 235 | print ("\t:$field[name]:"); 236 | if ($start != $stop) 237 | printf ("%u-%u\n", $start, $stop); 238 | else 239 | printf ("%u\n", $start); 240 | } 241 | } 242 | } 243 | } 244 | foreach ($registers_by_address as $addr => $addrregs) { 245 | foreach( $addrregs as $reg) { 246 | printf( "%-64s%s%s\n" 247 | , $reg['name'] 248 | , $addr 249 | , ('L' != $reg['width']) ? ('.'.$reg['width']) : '' ); 250 | if (isset($reg['fields'])) { 251 | $idx = $reg['fields']; 252 | $usage = $fieldset_usage[$idx]; 253 | if (1 == $usage) { 254 | $fields = $fieldsets[$idx]; 255 | foreach ($fields as $idx => $field) { 256 | if (is_int($idx)) { 257 | $start = $field['start']; 258 | $stop = $field['stop']; 259 | print ("\t:$field[name]:"); 260 | if ($start != $stop) 261 | printf ("%u-%u\n", $start, $stop); 262 | else 263 | printf ("%u\n", $start); 264 | } 265 | } 266 | } else { 267 | printf("\t:fs$idx/\n"); 268 | } 269 | } 270 | } 271 | } 272 | } else 273 | print( "Usage: $argv[0] inFile\n"); 274 | ?> 275 | -------------------------------------------------------------------------------- /debugPrint.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEBUGPRINT_H__ 2 | #define __DEBUGPRINT_H__ "$Id: debugPrint.h,v 1.5 2008-04-01 18:55:27 ericn Exp $" 3 | 4 | /* 5 | * debugPrint.h 6 | * 7 | * This header file declares the debugPrint() routine, 8 | * which is used to print debug information if the DEBUGPRINT 9 | * macro is set. 10 | * 11 | * 12 | * Change History : 13 | * 14 | * $Log: debugPrint.h,v $ 15 | * Revision 1.5 2008-04-01 18:55:27 ericn 16 | * -make NODEBUGPRINT easier 17 | * 18 | * Revision 1.4 2005/11/05 20:22:32 ericn 19 | * -fix compiler warnings 20 | * 21 | * Revision 1.3 2004/07/28 14:27:27 ericn 22 | * -prevent linking of empty debugPrint 23 | * 24 | * Revision 1.2 2004/07/04 21:33:16 ericn 25 | * -added debugHex() routine 26 | * 27 | * Revision 1.1 2003/11/24 19:42:42 ericn 28 | * -polling touch screen 29 | * 30 | * 31 | * 32 | * Copyright Boundary Devices, Inc. 2003 33 | */ 34 | 35 | #ifdef ANDROID 36 | #include 37 | #else 38 | #include 39 | #endif 40 | 41 | inline int noDebugPrint( char const *, ... ) 42 | { 43 | return 0 ; 44 | } 45 | 46 | #ifdef DEBUGPRINT 47 | #include 48 | #include 49 | 50 | #ifdef ANDROID 51 | #define debugPrint LOGD 52 | #else 53 | inline int debugPrint( char const *fmt, ... ) 54 | { 55 | va_list ap; 56 | va_start( ap, fmt ); 57 | return vfprintf( stdout, fmt, ap ); 58 | } 59 | #endif 60 | #else 61 | #define debugPrint noDebugPrint 62 | #endif 63 | 64 | #ifdef ANDROID 65 | #define ERRMSG LOGE 66 | #else 67 | inline int errmsg( char const *fmt, ... ) 68 | { 69 | va_list ap; 70 | va_start( ap, fmt ); 71 | return vfprintf( stderr, fmt, ap ); 72 | } 73 | #define ERRMSG errmsg 74 | #endif 75 | 76 | #endif 77 | 78 | -------------------------------------------------------------------------------- /fb2_overlay.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module fb2_overlay.cpp 3 | * 4 | * This module defines the methods of the fb2_overlay_t 5 | * class as declared in fb2_overlay.h 6 | * 7 | * Copyright Boundary Devices, Inc. 2010 8 | */ 9 | 10 | #include "fb2_overlay.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "fourcc.h" 23 | 24 | #define DEBUGPRINT 25 | #include "debugPrint.h" 26 | 27 | #ifndef ANDROID 28 | #define DEVNAME "/dev/fb2" 29 | #else 30 | #define DEVNAME "/dev/graphics/fb2" 31 | #endif 32 | 33 | fb2_overlay_t::fb2_overlay_t(unsigned outx, unsigned outy, 34 | unsigned outw, unsigned outh, 35 | unsigned transparency, 36 | unsigned color_key, 37 | unsigned long outformat, 38 | unsigned which_display ) 39 | : fd_(open(DEVNAME,O_RDWR|O_NONBLOCK)) 40 | , mem_(MAP_FAILED) 41 | , memSize_(0) 42 | { 43 | if ( 0 > fd_ ) { 44 | ERRMSG(DEVNAME); 45 | return ; 46 | } 47 | fcntl( fd_, F_SETFD, FD_CLOEXEC ); 48 | struct fb_fix_screeninfo fixed_info; 49 | int err = ioctl( fd_, FBIOGET_FSCREENINFO, &fixed_info); 50 | if ( 0 == err ) { 51 | struct fb_var_screeninfo variable_info; 52 | 53 | err = ioctl( fd_, FBIOGET_VSCREENINFO, &variable_info ); 54 | if ( 0 == err ) { 55 | if ((outw != variable_info.xres) 56 | || 57 | (outh != variable_info.yres) 58 | || 59 | (outformat != variable_info.nonstd)) { 60 | variable_info.xres = variable_info.xres_virtual = outw ; 61 | variable_info.yres = outh ; 62 | variable_info.yres_virtual = outh*2 ; 63 | variable_info.nonstd = outformat ; 64 | variable_info.bits_per_pixel = bits_per_pixel(outformat); 65 | err = ioctl( fd_, FBIOPUT_VSCREENINFO, &variable_info ); 66 | if (err) { 67 | perror( "FBIOPUT_VSCREENINFO"); 68 | close(); 69 | return ; 70 | } 71 | } // need to change output size 72 | struct mxcfb_pos pos ; 73 | pos.x = outx ; 74 | pos.y = outy ; 75 | err = ioctl(fd_,MXCFB_SET_OVERLAY_POS, &pos); 76 | if (err) { 77 | perror("MXCFB_SET_OVERLAY_POS"); 78 | close(); 79 | return ; 80 | } 81 | 82 | struct mxcfb_gbl_alpha a ; 83 | a.enable = (NO_TRANSPARENCY != transparency); 84 | a.alpha = transparency ; 85 | int err = ioctl(fd_,MXCFB_SET_GBL_ALPHA,&a); 86 | if ( err ) { 87 | perror( "MXCFB_SET_GBL_ALPHA"); 88 | close(); 89 | return ; 90 | } 91 | struct mxcfb_color_key key; 92 | key.enable = 0xFFFF >= color_key ; 93 | key.color_key = color_key; 94 | if (ioctl(fd_,MXCFB_SET_CLR_KEY, &key) <0) { 95 | perror("MXCFB_SET_CLR_KEY error!"); 96 | ::close(fd_); 97 | close(); 98 | return ; 99 | } 100 | 101 | memSize_ = fixed_info.smem_len ; 102 | mem_ = mmap( 0, fixed_info.smem_len, PROT_WRITE|PROT_WRITE, MAP_SHARED, fd_, 0 ); 103 | if ( MAP_FAILED != mem_ ) { 104 | unsigned value ; 105 | printf( "mapped %u (0x%lx) bytes\n", fixed_info.smem_len, memSize_ ); 106 | err = ioctl( fd_, FBIOBLANK, VESA_NO_BLANKING ); 107 | if ( err ) { 108 | perror("FBIOBLANK"); 109 | close(); 110 | return ; 111 | } 112 | if (ioctl(fd_,MXCFB_GET_FB_IPU_CHAN, &value) <0) 113 | perror("MXCFB_GET_FB_IPU_CHAN error!"); 114 | else 115 | printf( "MXCFB_GET_FB_IPU_CHAN: %x\n", value ); 116 | if (ioctl(fd_,MXCFB_GET_FB_IPU_DI, &value) <0) 117 | perror("MXCFB_GET_FB_IPU_DI error!"); 118 | else 119 | printf( "MXCFB_GET_FB_IPU_DI: %x\n", value ); 120 | if (ioctl(fd_,MXCFB_GET_DIFMT, &value) <0) 121 | perror("MXCFB_GET_DIFMT error!"); 122 | else 123 | printf( "MXCFB_GET_DIFMT: %x\n", value ); 124 | memset(mem_, 0x80, fixed_info.smem_len); 125 | } 126 | else 127 | perror( "VSCREENINFO" ); 128 | } 129 | else 130 | perror( "FSCREENINFO" ); 131 | } 132 | else 133 | perror(DEVNAME); 134 | } 135 | 136 | fb2_overlay_t::~fb2_overlay_t( void ) 137 | { 138 | if (isOpen()) 139 | close(); 140 | } 141 | 142 | void fb2_overlay_t::close( void ){ 143 | if ( 0 <= fd_ ) { 144 | int err = ioctl( fd_, FBIOBLANK, VESA_POWERDOWN ); 145 | if ( err ) 146 | perror("FBIOBLANK"); 147 | if ( MAP_FAILED != mem_ ) { 148 | err = munmap(mem_, memSize_); 149 | if ( err ) 150 | perror( "munmap"); 151 | } 152 | ::close(fd_); 153 | fd_ = -1 ; 154 | } 155 | } 156 | 157 | #ifdef OVERLAY_MODULETEST 158 | 159 | #include 160 | 161 | unsigned x = 0 ; 162 | unsigned y = 0 ; 163 | unsigned outw = 480 ; 164 | unsigned outh = 272 ; 165 | unsigned alpha = 0 ; 166 | unsigned format = V4L2_PIX_FMT_NV12 ; 167 | unsigned which_display = 0 ; 168 | char const *inFile = 0 ; 169 | 170 | static void parseArgs( int &argc, char const **argv ) 171 | { 172 | for ( int arg = 1 ; arg < argc ; arg++ ) { 173 | if ( '-' == *argv[arg] ) { 174 | char const *param = argv[arg]+1 ; 175 | char const cmdchar = tolower(*param); 176 | if ( 'i' == cmdchar ) { 177 | inFile = param+1 ; 178 | printf( "input file is <%s>\n", inFile ); 179 | } 180 | else if ( 'o' == cmdchar ) { 181 | char const second = tolower(param[1]); 182 | if ('w' == second) { 183 | outw = strtoul(param+2,0,0); 184 | } 185 | else if ('h'==second) { 186 | outh = strtoul(param+2,0,0); 187 | } 188 | else 189 | printf( "unknown output option %c\n",second); 190 | } 191 | else if ( 'x' == cmdchar ) { 192 | x = strtoul(param+1,0,0); 193 | } 194 | else if ( 'y' == cmdchar ) { 195 | y = strtoul(param+1,0,0); 196 | } 197 | else if (('a' == cmdchar)||('t' == cmdchar)) { 198 | alpha = strtoul(param+1,0,0); 199 | } 200 | else if ('d' == cmdchar){ 201 | which_display = strtoul(param+1,0,0); 202 | } 203 | else if ( 'f' == cmdchar ) { 204 | unsigned fcc ; 205 | if(supported_fourcc(param+1,fcc)){ 206 | format = fcc ; 207 | } else { 208 | fprintf(stderr, "Invalid format %s\n", param+1 ); 209 | fprintf(stderr, "supported formats include:\n" ); 210 | unsigned const *formats ; unsigned num_formats ; 211 | supported_fourcc_formats(formats,num_formats); 212 | while( num_formats-- ){ 213 | fprintf(stderr, "\t%s\n", fourcc_str(*formats)); 214 | formats++ ; 215 | } 216 | exit(1); 217 | } 218 | } 219 | else 220 | printf( "unknown option %s\n", param ); 221 | 222 | // pull from argument list 223 | for ( int j = arg+1 ; j < argc ; j++ ) { 224 | argv[j-1] = argv[j]; 225 | } 226 | --arg ; 227 | --argc ; 228 | } 229 | } 230 | } 231 | 232 | static void trimCtrl(char *buf){ 233 | char *tail = buf+strlen(buf); 234 | // trim trailing if needed 235 | while ( tail > buf ) { 236 | --tail ; 237 | if ( iscntrl(*tail) ) { 238 | *tail = '\0' ; 239 | } 240 | else 241 | break; 242 | } 243 | } 244 | 245 | #define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ 246 | 247 | int main( int argc, char const **argv ) { 248 | parseArgs(argc,argv); 249 | 250 | printf( "%ux%u on /dev/fb%u\n", outw, outh, which_display ); 251 | 252 | fb2_overlay_t overlay(x,y,outw,outh,alpha,format,which_display); // V4L2_PIX_FMT_SGRBG8 ; // 253 | if ( overlay.isOpen() ) { 254 | printf( "opened successfully: mem=%p/%u\n", overlay.getMem(), overlay.getMemSize() ); 255 | unsigned char val = 0 ; 256 | while(1){ 257 | memset(overlay.getMem(), val++, overlay.getMemSize()); 258 | } 259 | } 260 | else 261 | ERRMSG( "Error opening v4l output\n" ); 262 | return 0 ; 263 | } 264 | #endif 265 | -------------------------------------------------------------------------------- /fb2_overlay.h: -------------------------------------------------------------------------------- 1 | #ifndef __FB2_OVERLAY_H__ 2 | #define __FB2_OVERLAY_H__ "$Id$" 3 | 4 | /* 5 | * fb2_overlay.h 6 | * 7 | * This header file declares the fb2_overlay_t class, which is 8 | * used to display a YUV overlay on an i.MX51 processor. 9 | * 10 | * When constructed with a specified input widtn and height 11 | * and output rectangle, this class will attempt to open the 12 | * YUV device and configure it as specified. 13 | * 14 | * Usage generally involves checking for success (isOpen()), 15 | * then memcpy'ing to the frame buffer 16 | * 17 | * Change History : 18 | * 19 | * $Log$ 20 | * 21 | * 22 | * Copyright Boundary Devices, Inc. 2010 23 | */ 24 | 25 | class fb2_overlay_t { 26 | public: 27 | enum { 28 | NO_TRANSPARENCY = 0xffffffff 29 | }; 30 | fb2_overlay_t( 31 | unsigned outx, unsigned outy, 32 | unsigned outw, unsigned outh, 33 | unsigned transparency, // 0(transparent)..255(opaque) or NO_TRANSPARENCY 34 | unsigned color_key, // > 0xFFFF means none 35 | unsigned long outfmt, // fourcc 36 | unsigned which_display=0 );// /dev/fbX 37 | ~fb2_overlay_t( void ); 38 | 39 | bool isOpen( void ) const { return 0 <= fd_ ;} 40 | int getFd( void ) const { return fd_ ;} 41 | 42 | void *getMem( void ) const { return mem_ ; } 43 | unsigned getMemSize( void ) const { return memSize_ ; } 44 | private: 45 | void close(void); 46 | 47 | fb2_overlay_t( fb2_overlay_t const & ); // no copies 48 | unsigned long outfmt_ ; 49 | int fd_ ; 50 | void *mem_ ; 51 | unsigned long memSize_ ; 52 | }; 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /fbSet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * fbSet.cpp 3 | * 4 | * Simple illustration of access to the Frame Buffer 5 | * via mmap. 6 | * 7 | * Copyright Boundary Devices, 2005 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "fourcc.h" 21 | 22 | int main( int argc, char const * const argv[] ) 23 | { 24 | if( 2 <= argc ) 25 | { 26 | int const fd = open( argv[1], O_RDWR ); 27 | if( 0 <= fd ) 28 | { 29 | fcntl( fd, F_SETFD, FD_CLOEXEC ); 30 | struct fb_fix_screeninfo fixed_info; 31 | int err = ioctl( fd, FBIOGET_FSCREENINFO, &fixed_info); 32 | if( 0 == err ) 33 | { 34 | printf( "id %s\n", fixed_info.id ); 35 | printf( "smem_start 0x%lx\n", fixed_info.smem_start ); 36 | printf( "smem_len %u\n", fixed_info.smem_len ); 37 | printf( "type %u\n", fixed_info.type ); 38 | printf( "type_aux %u\n", fixed_info.type_aux ); 39 | printf( "visual %u\n", fixed_info.visual ); 40 | printf( "xpan %u\n", fixed_info.xpanstep ); 41 | printf( "ypan %u\n", fixed_info.ypanstep ); 42 | printf( "ywrap %u\n", fixed_info.ywrapstep ); 43 | printf( "line_len %u\n", fixed_info.line_length ); 44 | printf( "mmio_start %lu\n", fixed_info.mmio_start ); 45 | printf( "mmio_len %u\n", fixed_info.mmio_len ); 46 | printf( "accel %u\n", fixed_info.accel ); 47 | struct fb_var_screeninfo variable_info; 48 | 49 | err = ioctl( fd, FBIOGET_VSCREENINFO, &variable_info ); 50 | if( 0 == err ) 51 | { 52 | printf( "xres = %u\n", variable_info.xres ); // visible resolution 53 | printf( "yres = %u\n", variable_info.yres ); 54 | printf( "xres_virtual = %u\n", variable_info.xres_virtual ); // virtual resolution 55 | printf( "yres_virtual = %u\n", variable_info.yres_virtual ); 56 | printf( "xoffset = %u\n", variable_info.xoffset ); // offset from virtual to visible 57 | printf( "yoffset = %u\n", variable_info.yoffset ); // resolution 58 | printf( "bits_per_pixel = %u\n", variable_info.bits_per_pixel ); // guess what 59 | printf( "grayscale = %u\n", variable_info.grayscale ); // != 0 Graylevels instead of colors 60 | 61 | printf( "red = offs %u, len %u, msbr %u\n", 62 | variable_info.red.offset, 63 | variable_info.red.length, 64 | variable_info.red.msb_right ); 65 | printf( "green = offs %u, len %u, msbr %u\n", 66 | variable_info.green.offset, 67 | variable_info.green.length, 68 | variable_info.green.msb_right ); 69 | printf( "blue = offs %u, len %u, msbr %u\n", 70 | variable_info.blue.offset, 71 | variable_info.blue.length, 72 | variable_info.blue.msb_right ); 73 | 74 | printf( "nonstd = 0x%x - %s\n", variable_info.nonstd, fourcc_str(variable_info.nonstd) ); // != 0 Non standard pixel format 75 | printf( "activate = %u\n", variable_info.activate ); // see FB_ACTIVATE_* 76 | printf( "height = %u\n", variable_info.height ); // height of picture in mm 77 | printf( "width = %u\n", variable_info.width ); // width of picture in mm 78 | printf( "accel_flags = %u\n", variable_info.accel_flags ); // acceleration flags (hints) 79 | printf( "pixclock = %u\n", variable_info.pixclock ); // pixel clock in ps (pico seconds) 80 | printf( "left_margin = %u\n", variable_info.left_margin ); // time from sync to picture 81 | printf( "right_margin = %u\n", variable_info.right_margin ); // time from picture to sync 82 | printf( "upper_margin = %u\n", variable_info.upper_margin ); // time from sync to picture 83 | printf( "lower_margin = %u\n", variable_info.lower_margin ); 84 | printf( "hsync_len = %u\n", variable_info.hsync_len ); // length of horizontal sync 85 | printf( "vsync_len = %u\n", variable_info.vsync_len ); // length of vertical sync 86 | printf( "sync = %u\n", variable_info.sync ); // see FB_SYNC_* 87 | printf( "vmode = %u\n", variable_info.vmode ); // see FB_VMODE_* 88 | 89 | printf( "%u x %u --> %u bytes\n", 90 | variable_info.xres, variable_info.yres, fixed_info.smem_len ); 91 | 92 | if( 2 < argc ){ 93 | unsigned long rgb = strtoul( argv[2], 0, 0 ); 94 | void *mem = mmap( 0, fixed_info.smem_len, PROT_WRITE|PROT_WRITE, 95 | MAP_SHARED, fd, 0 ); 96 | if( MAP_FAILED != mem ) 97 | { 98 | unsigned char red = (unsigned char)(rgb>>16); 99 | unsigned char green = (unsigned char)(rgb>>8); 100 | unsigned char blue = (unsigned char)(rgb); 101 | unsigned short rgb16 = ((unsigned short)(red>>(8-variable_info.red.length)) << 11) // 5 bits of red 102 | | ((unsigned short)(green>>(8-variable_info.green.length)) << 5) // 6 bits of green 103 | | ((unsigned short)(blue>>(8-variable_info.blue.length))); // 5 bits of blue 104 | unsigned long doubled = ( ((unsigned long)rgb16) << 16 ) 105 | | rgb16 ; 106 | memset( mem, doubled, fixed_info.smem_len ); 107 | } 108 | else 109 | perror( "mmap fb" ); 110 | } 111 | } 112 | else 113 | perror( "VSCREENINFO" ); 114 | } 115 | else 116 | perror( "FSCREENINFO" ); 117 | } 118 | else 119 | perror( argv[1] ); 120 | } 121 | else 122 | fprintf( stderr, "Usage: fbSet /dev/fb0 0xFFFFFF\n" ); 123 | return 0 ; 124 | } 125 | -------------------------------------------------------------------------------- /flipper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | inline void noprintf(...){} 13 | #define debugPrint noprintf 14 | 15 | class fbDevice_t { 16 | public: 17 | fbDevice_t(void); 18 | ~fbDevice_t(void); 19 | 20 | bool isOpen(void){return 0 <= fd_ ;} 21 | void clear(unsigned short color); 22 | void hline(unsigned l,unsigned short color); 23 | void vline(unsigned l,unsigned short color); 24 | void flip(); 25 | unsigned getWidth(void) const { return width_; } 26 | unsigned getHeight(void) const { return height_; } 27 | unsigned short *getMem(void) const { return (unsigned short *)(((char *)mem_)+(screenSize_*curBuf_)); } 28 | void set_cur_buf(unsigned cur) { curBuf_ = cur; } 29 | private: 30 | int fd_ ; 31 | unsigned short *mem_ ; 32 | unsigned long memSize_ ; 33 | unsigned short width_ ; 34 | unsigned short height_ ; 35 | unsigned short stride_; 36 | unsigned curBuf_ ; 37 | unsigned screenSize_ ; 38 | struct fb_var_screeninfo var ; 39 | }; 40 | 41 | #ifdef ANDROID 42 | #define FBDEVNAME "/dev/graphics/fb0" 43 | #else 44 | #define FBDEVNAME "/dev/fb0" 45 | #endif 46 | 47 | fbDevice_t::fbDevice_t(void) 48 | : fd_(open(FBDEVNAME,O_RDWR)) 49 | , mem_(0) 50 | , memSize_(0) 51 | , width_(0) 52 | , height_(0) 53 | , stride_(0) 54 | , curBuf_(0) 55 | , screenSize_(0) 56 | { 57 | 58 | if( 0 <= fd_ ){ 59 | fcntl( fd_, F_SETFD, FD_CLOEXEC ); 60 | struct fb_fix_screeninfo fixed_info; 61 | int err = ioctl( fd_, FBIOGET_FSCREENINFO, &fixed_info); 62 | if( 0 == err ){ 63 | struct fb_var_screeninfo variable_info; 64 | 65 | err = ioctl( fd_, FBIOGET_VSCREENINFO, &variable_info ); 66 | if( 0 == err ){ 67 | width_ = variable_info.xres ; 68 | height_ = variable_info.yres ; 69 | stride_ = fixed_info.line_length; 70 | memSize_ = fixed_info.smem_len ; 71 | screenSize_ = height_*stride_ ; 72 | mem_ = (unsigned short *)mmap( 0, memSize_, PROT_WRITE|PROT_WRITE, MAP_SHARED, fd_, 0 ); 73 | if( MAP_FAILED != (void *)mem_ ) 74 | { 75 | var = variable_info ; 76 | debugPrint( "mem at %p\n", mem_ ); 77 | return ; 78 | } 79 | else 80 | perror( "mmap fb" ); 81 | } 82 | else 83 | perror("FBIOGET_VSCREENINFO"); 84 | } 85 | else 86 | perror("FBIOGET_FSCREENINFO"); 87 | 88 | ::close(fd_); 89 | fd_ = -1 ; 90 | } else 91 | perror(FBDEVNAME); 92 | } 93 | 94 | fbDevice_t::~fbDevice_t(void) 95 | { 96 | if( isOpen() ){ 97 | ::close(fd_); 98 | fd_ = -1 ; 99 | } 100 | } 101 | 102 | void fbDevice_t::clear(unsigned short color) 103 | { 104 | if(isOpen()){ 105 | unsigned long clong=(color<<16)|color; 106 | memset(mem_,clong,memSize_); 107 | } 108 | } 109 | 110 | void fbDevice_t::hline(unsigned l,unsigned short color){ 111 | unsigned short *buf = getMem(); 112 | debugPrint( "line in buf %p, color %x\n", buf,color); 113 | buf += (stride_*l)/sizeof(*buf); 114 | unsigned long clong=(color<<16)|color; 115 | memset(buf,color,stride_); 116 | } 117 | 118 | void fbDevice_t::vline(unsigned l,unsigned short color){ 119 | unsigned short *buf = getMem(); 120 | unsigned h = getHeight(); 121 | debugPrint( "line in buf %p, color %x\n", buf,color); 122 | buf += l; 123 | while (h) { 124 | *buf = color; 125 | buf = (unsigned short*)(((unsigned char*)buf) + stride_); 126 | h--; 127 | } 128 | } 129 | 130 | #define MXCFB_WAIT_FOR_VSYNC _IOW('F', 0x20, u_int32_t) 131 | 132 | void fbDevice_t::flip(){ 133 | var.yoffset = curBuf_*height_; 134 | int err ; 135 | again: 136 | err = ioctl(fd_,MXCFB_WAIT_FOR_VSYNC,0); 137 | if (0 != err) 138 | perror("MXCFB_WAIT_FOR_VSYNC"); 139 | err = ioctl(fd_,FBIOPAN_DISPLAY,&var); 140 | if(err) { 141 | perror("FBIOPAN_DISPLAY"); 142 | if (-EBUSY == err) { 143 | goto again ; 144 | } 145 | } else 146 | printf( "flipped to buffer %u\n", curBuf_ ); 147 | } 148 | 149 | int main(int argc, char const * const argv[]){ 150 | fbDevice_t fb ; 151 | if( fb.isOpen() ){ 152 | fb.clear(0xffff); 153 | unsigned prevline[2]; 154 | unsigned line[2]; 155 | unsigned cur = 0; 156 | prevline[0] = prevline[1] = 0; 157 | line[0] = 0; 158 | line[1] = 1; 159 | while(1){ 160 | fb.set_cur_buf(cur); 161 | fb.vline(prevline[cur],0xffff); 162 | fb.vline(line[cur],0); 163 | prevline[cur] = line[cur]; 164 | line[cur] = (line[cur]+2)%fb.getWidth(); 165 | fb.flip(); 166 | cur ^= 1; 167 | } 168 | } else 169 | perror( "fbdev"); 170 | return 0 ; 171 | } 172 | -------------------------------------------------------------------------------- /fourcc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module fourcc.cpp 3 | * 4 | * This module defines the fourcc utility routines described 5 | * in fourcc.h 6 | * 7 | * Change History : 8 | * 9 | * $Log$ 10 | * 11 | * Copyright Boundary Devices, Inc. 2010 12 | */ 13 | 14 | #include "fourcc.h" 15 | #include 16 | #include 17 | #include 18 | 19 | #define ARRAY_SIZE(__arr) (sizeof(__arr)/sizeof(__arr[0])) 20 | 21 | enum colorspace { 22 | YUV, 23 | RGB 24 | }; 25 | 26 | #define PXF_PLANAR 1 27 | #define PXF_PLANAR_UV_W_HALF 2 28 | #define PXF_PLANAR_UV_H_HALF 4 29 | #define PXF_COLORSPACE_YUV 8 30 | #define PXF_PLANAR_PARTIAL 16 31 | #define PXF_PLANAR_V_FIRST 32 32 | #define PXF_COLORSPACE_YV_FIRST 64 33 | 34 | struct pixformat_info { 35 | unsigned v4l2_format ; 36 | char const *name ; 37 | unsigned bytes_per_component ; 38 | enum colorspace colorspace ; 39 | unsigned flags ; 40 | }; 41 | 42 | static const struct pixformat_info pix_formats[] = { 43 | {V4L2_PIX_FMT_YUV420, "YUV420", 1, YUV, PXF_PLANAR | PXF_PLANAR_UV_W_HALF | PXF_PLANAR_UV_H_HALF}, 44 | {V4L2_PIX_FMT_YVU420, "YVU420", 1, YUV, PXF_PLANAR | PXF_PLANAR_UV_W_HALF | PXF_PLANAR_UV_H_HALF | PXF_PLANAR_V_FIRST}, 45 | {V4L2_PIX_FMT_NV12, "NV12", 1, YUV, PXF_PLANAR | PXF_PLANAR_UV_W_HALF | PXF_PLANAR_UV_H_HALF | PXF_PLANAR_PARTIAL}, 46 | {V4L2_PIX_FMT_YUV422P, "YUV422P", 1, YUV, PXF_PLANAR | PXF_PLANAR_UV_W_HALF}, 47 | {v4l2_fourcc('Y','V','1','6'),"YVU422P", 1, YUV, PXF_PLANAR | PXF_PLANAR_UV_W_HALF | PXF_PLANAR_V_FIRST}, 48 | {V4L2_PIX_FMT_SBGGR8, "SBGGR8", 1, RGB, 0}, 49 | {V4L2_PIX_FMT_SGBRG8, "SGBRG8", 1, RGB, 0}, 50 | {V4L2_PIX_FMT_SGRBG10, "SGRBG10", 2, RGB, 0}, 51 | {V4L2_PIX_FMT_SBGGR16, "SBGGR16", 2, RGB, 0}, 52 | {V4L2_PIX_FMT_RGB565, "RGB565", 2, RGB, 0}, 53 | {V4L2_PIX_FMT_UYVY, "UYVY", 2, YUV, 0}, 54 | {V4L2_PIX_FMT_YUYV, "YUYV", 2, YUV, 0}, 55 | {V4L2_PIX_FMT_RGB24, "RGB24", 3, RGB, 0}, 56 | {V4L2_PIX_FMT_BGR24, "BGR24", 3, RGB, 0}, 57 | {V4L2_PIX_FMT_RGB32, "RGB32", 4, RGB, 0}, 58 | {V4L2_PIX_FMT_BGR32, "BGR32", 4, RGB, 0}, 59 | }; 60 | 61 | unsigned bits_per_pixel(unsigned fourcc) 62 | { 63 | for( unsigned i = 0 ; i < ARRAY_SIZE(pix_formats); i++ ){ 64 | if(fourcc == pix_formats[i].v4l2_format) 65 | return pix_formats[i].bytes_per_component*8 ; 66 | } 67 | return 0 ; 68 | } 69 | 70 | static unsigned const *supported_formats = 0 ; 71 | 72 | bool supported_fourcc(char const *arg, unsigned &fourcc){ 73 | fourcc = fourcc_from_str(arg); 74 | for( unsigned i = 0 ; i < ARRAY_SIZE(pix_formats); i++ ){ 75 | if(fourcc == pix_formats[i].v4l2_format) 76 | return true ; 77 | } 78 | return false ; 79 | } 80 | 81 | bool supported_fourcc(unsigned fourcc){ 82 | for( unsigned i = 0 ; i < ARRAY_SIZE(pix_formats); i++ ){ 83 | if(fourcc == pix_formats[i].v4l2_format) 84 | return true ; 85 | } 86 | return false ; 87 | } 88 | 89 | void supported_fourcc_formats(unsigned const *&values, unsigned &numValues) 90 | { 91 | if( 0 == supported_formats ){ 92 | unsigned *fmts = new unsigned [ARRAY_SIZE(pix_formats)]; 93 | for( unsigned i = 0 ; i < ARRAY_SIZE(pix_formats); i++ ){ 94 | fmts[i] = pix_formats[i].v4l2_format ; 95 | } 96 | supported_formats = (unsigned const *)fmts ; 97 | } 98 | 99 | values = supported_formats ; 100 | numValues = ARRAY_SIZE(pix_formats); 101 | } 102 | 103 | bool isYUV(unsigned fourcc) 104 | { 105 | for( unsigned i = 0 ; i < ARRAY_SIZE(pix_formats); i++ ){ 106 | if(fourcc == pix_formats[i].v4l2_format) 107 | return YUV == pix_formats[i].colorspace ; 108 | } 109 | return false ; 110 | } 111 | 112 | /* 113 | * In order to iterate through each of the bytes of Y, U, and V for each supported YUV frame 114 | * format we need to know each of these for Y, U, and V. 115 | * 116 | * initial offset 117 | * row divisor 118 | * column divisor 119 | * column adder 120 | * 121 | * In order to produce these, we'll need the width, height and fourcc value coming in. 122 | * The following table will allow these calculations based on multipliers, divisors and 123 | * fixed offsets based on W*H and W (height doesn't matter). 124 | * 125 | * The initial offset calculation is this: 126 | * initial offset = (imwh_numerator*(W*H)/imwh_denominator) + (imw_numerator*W)/imw_denominator + fixed_offset ; 127 | * 128 | * The column divisors and adders are strictly constants. 129 | * 130 | */ 131 | struct multiplier { 132 | unsigned num ; 133 | unsigned denom ; 134 | }; 135 | 136 | struct scaler { 137 | struct multiplier whmult ; 138 | struct multiplier wmult ; 139 | unsigned initial_offset ; 140 | unsigned row_divisor ; 141 | unsigned column_divisor ; 142 | unsigned column_adder ; 143 | }; 144 | 145 | struct yuvOffsets_t { 146 | unsigned fourcc ; 147 | struct scaler yscaler ; 148 | struct scaler uscaler ; 149 | struct scaler vscaler ; 150 | }; 151 | 152 | /* 153 | * To take an example: YUV420P consists of an [W*H] Y plane followed by [W*H/4] U and V planes, so 154 | * its table entry will be this: 155 | * 156 | * Y: WH W offset rd cd ca Y: WH W offset rd cd ca Y: WH W offset rd cd ca 157 | * {{0,1}, {0,1}, 0, 1, 1, 1}}, {{1,1}, {0,1}, 0, 2, 2, 1}}, {{0,1}, {0,1}, 0, 2, 2, 1}}, 158 | * 159 | * In English, all of the initial offsets yield zero for Y, the U plane is offset by 1*W*H and the V plane is offset by (5/4)*W*H (1.25). 160 | * Both row and column divisors are 1 for Y and 2 for both U and V planes. 161 | * All of the column adders are 1, so adjacent columns are adjacent in memory. 162 | * 163 | * For the YUYV format, each of the W*H and W multipliers will yield zero, the fixed offsets will be 0, 1, and 3 for Y, U, and V and 164 | * the column adders will be 2, 4, and 4 since the Y values are two bytes apart in memory and U and V are two bytes apart. 165 | * 166 | */ 167 | static struct yuvOffsets_t const yuvOffsets[] = { 168 | { V4L2_PIX_FMT_YUV420, // YUV 420 planar 169 | { {0,1} // Y: W*H multiplier 170 | , {0,1} // W multiplier 171 | , 0 // initial offset 172 | , 1 // row divisor 173 | , 1 // column divisor 174 | , 1 // column adder 175 | } 176 | , { {1,1} // U: W*H multiplier 177 | , {0,1} // W multiplier 178 | , 0 // initial offset 179 | , 2 // row divisor 180 | , 2 // column divisor 181 | , 1 // column adder 182 | } 183 | , { {5,4} // V: W*H multiplier 184 | , {0,1} // W multiplier 185 | , 0 // initial offset 186 | , 2 // row divisor 187 | , 2 // column divisor 188 | , 1 // column adder 189 | } 190 | } 191 | , { V4L2_PIX_FMT_YVU420, // YUV 420 planar 192 | { {0,1} // Y: W*H multiplier 193 | , {0,1} // W multiplier 194 | , 0 // initial offset 195 | , 1 // row divisor 196 | , 1 // column divisor 197 | , 1 // column adder 198 | } 199 | , { {5,4} // U: W*H multiplier 200 | , {0,1} // W multiplier 201 | , 0 // initial offset 202 | , 2 // row divisor 203 | , 2 // column divisor 204 | , 1 // column adder 205 | } 206 | , { {1,1} // V: W*H multiplier 207 | , {0,1} // W multiplier 208 | , 0 // initial offset 209 | , 2 // row divisor 210 | , 2 // column divisor 211 | , 1 // column adder 212 | } 213 | } 214 | , { V4L2_PIX_FMT_NV12, // YUV 420 semi-planar 215 | { {0,1} // Y: W*H multiplier 216 | , {0,1} // W multiplier 217 | , 0 // initial offset 218 | , 1 // row divisor 219 | , 1 // column divisor 220 | , 1 // column adder 221 | } 222 | , { {1,1} // U: W*H multiplier 223 | , {0,1} // W multiplier 224 | , 0 // initial offset 225 | , 2 // row divisor 226 | , 2 // column divisor 227 | , 2 // column adder 228 | } 229 | , { {1,1} // V: W*H multiplier 230 | , {0,1} // W multiplier 231 | , 1 // initial offset 232 | , 2 // row divisor 233 | , 2 // column divisor 234 | , 2 // column adder 235 | } 236 | } 237 | , { V4L2_PIX_FMT_YUV422P, // YUV 422 planar 238 | { {0,1} // Y: W*H multiplier 239 | , {0,1} // W multiplier 240 | , 0 // initial offset 241 | , 1 // row divisor 242 | , 1 // column divisor 243 | , 1 // column adder 244 | } 245 | , { {1,1} // U: W*H multiplier 246 | , {0,1} // W multiplier 247 | , 0 // initial offset 248 | , 1 // row divisor 249 | , 2 // column divisor 250 | , 1 // column adder 251 | } 252 | , { {3,2} // V: W*H multiplier 253 | , {0,1} // W multiplier 254 | , 0 // initial offset 255 | , 1 // row divisor 256 | , 2 // column divisor 257 | , 1 // column adder 258 | } 259 | } 260 | , { V4L2_PIX_FMT_YUYV, // YUYV 261 | { {0,1} // Y: W*H multiplier 262 | , {0,1} // W multiplier 263 | , 0 // initial offset 264 | , 1 // row divisor 265 | , 1 // column divisor 266 | , 2 // column adder 267 | } 268 | , { {0,1} // U: W*H multiplier 269 | , {0,1} // W multiplier 270 | , 1 // initial offset 271 | , 1 // row divisor 272 | , 2 // column divisor 273 | , 4 // column adder 274 | } 275 | , { {0,1} // V: W*H multiplier 276 | , {0,1} // W multiplier 277 | , 3 // initial offset 278 | , 1 // row divisor 279 | , 2 // column divisor 280 | , 4 // column adder 281 | } 282 | } 283 | , { V4L2_PIX_FMT_UYVY, // UYVY 284 | { {0,1} // Y: W*H multiplier 285 | , {0,1} // W multiplier 286 | , 1 // initial offset 287 | , 1 // row divisor 288 | , 1 // column divisor 289 | , 2 // column adder 290 | } 291 | , { {0,1} // U: W*H multiplier 292 | , {0,1} // W multiplier 293 | , 0 // initial offset 294 | , 1 // row divisor 295 | , 2 // column divisor 296 | , 4 // column adder 297 | } 298 | , { {0,1} // V: W*H multiplier 299 | , {0,1} // W multiplier 300 | , 2 // initial offset 301 | , 1 // row divisor 302 | , 2 // column divisor 303 | , 4 // column adder 304 | } 305 | } 306 | }; 307 | 308 | bool fourccOffsets( 309 | unsigned fourcc, 310 | unsigned width, 311 | unsigned height, 312 | unsigned &ysize, 313 | unsigned &yoffs, 314 | unsigned &yadder, 315 | unsigned &uvsize, 316 | unsigned &uvrowdiv, 317 | unsigned &uvcoldiv, 318 | unsigned &uoffs, 319 | unsigned &voffs, 320 | unsigned &uvadder, 321 | unsigned &totalsize ) 322 | { 323 | unsigned WH = width*height; 324 | for (unsigned i = 0 ; i < ARRAY_SIZE(yuvOffsets); i++) { 325 | struct yuvOffsets_t const &entry = yuvOffsets[i]; 326 | if (entry.fourcc==fourcc) { 327 | if ((entry.uscaler.row_divisor == entry.vscaler.row_divisor) 328 | && 329 | (entry.uscaler.column_divisor == entry.vscaler.column_divisor) 330 | && 331 | (entry.uscaler.column_adder == entry.vscaler.column_adder)) { 332 | ysize=(WH/entry.yscaler.row_divisor/entry.yscaler.column_divisor); 333 | uvsize=(WH/entry.uscaler.row_divisor/entry.uscaler.column_divisor); 334 | totalsize = ysize+2*uvsize; 335 | yadder = entry.yscaler.column_adder ; 336 | uvadder = entry.uscaler.column_adder ; 337 | uvrowdiv = entry.uscaler.row_divisor ; 338 | uvcoldiv = entry.uscaler.column_divisor ; 339 | yoffs = (WH*entry.yscaler.whmult.num)/entry.yscaler.whmult.denom 340 | + (width*entry.yscaler.wmult.num)/entry.yscaler.wmult.denom 341 | + entry.yscaler.initial_offset ; 342 | uoffs = (WH*entry.uscaler.whmult.num)/entry.uscaler.whmult.denom 343 | + (width*entry.uscaler.wmult.num)/entry.uscaler.wmult.denom 344 | + entry.uscaler.initial_offset ; 345 | voffs = (WH*entry.vscaler.whmult.num)/entry.vscaler.whmult.denom 346 | + (width*entry.vscaler.wmult.num)/entry.vscaler.wmult.denom 347 | + entry.vscaler.initial_offset ; 348 | return true ; 349 | } // this API can't handle different U and V sizes 350 | else { 351 | fprintf(stderr, "%s: Invalid fourcc for this API\n", __func__ ); 352 | break; 353 | } 354 | } 355 | } 356 | return false ; 357 | } 358 | 359 | #ifdef STANDALONE_FOURCC 360 | #include 361 | #include 362 | 363 | int main(int argc, char const * const argv[]){ 364 | if (1 < argc) { 365 | for( int arg = 1 ; arg < argc ; arg++ ){ 366 | unsigned binary = 0 ; 367 | bool supported = false ; 368 | char const *param = argv[arg]; 369 | if( '0' == *param ){ 370 | binary = strtoul(param,0,0); 371 | supported = supported_fourcc(binary); 372 | printf( "fourcc(%s:0x%08x) == '%s'%s\n", param, binary, fourcc_str(binary), supported ? " supported" : " not supported"); 373 | } else { 374 | binary = fourcc_from_str(param); 375 | supported = supported_fourcc(binary); 376 | printf( "fourcc(%s) == 0x%08x%s\n", param, binary, supported ? " supported" : " not supported"); 377 | } 378 | if(supported){ 379 | unsigned ysize ; 380 | unsigned yoffs ; 381 | unsigned yadder ; 382 | unsigned uvsize ; 383 | unsigned uvrowdiv ; 384 | unsigned uvcoldiv ; 385 | unsigned uoffs ; 386 | unsigned voffs ; 387 | unsigned uvadder ; 388 | unsigned totalsize ; 389 | if( fourccOffsets(binary,320,240,ysize,yoffs,yadder,uvsize,uvrowdiv,uvcoldiv,uoffs,voffs,uvadder,totalsize) ){ 390 | printf( "\tYUV format. For 320x240 surface:\n" 391 | " ySize %u\n" 392 | " yOffs %u\n" 393 | " yAdder %u\n" 394 | " uvSize %u\n" 395 | " uvRowDiv %u\n" 396 | " uvColDiv %u\n" 397 | " uOffs %u\n" 398 | " vOffs %u\n" 399 | " uvAdder %u\n" 400 | " totalsize %u\n" 401 | , ysize, yoffs, yadder, uvsize, uvrowdiv, uvcoldiv, uoffs, voffs, uvadder, totalsize 402 | ); 403 | } 404 | else 405 | printf( "RGB format\n" ); 406 | } 407 | } 408 | } 409 | else 410 | fprintf(stderr, "Usage: %s 0xvalue or STRG\n", argv[0]); 411 | 412 | return 0 ; 413 | } 414 | #endif 415 | -------------------------------------------------------------------------------- /fourcc.h: -------------------------------------------------------------------------------- 1 | #ifndef __FOURCC_H__ 2 | #define __FOURCC_H__ "$Id$" 3 | 4 | /* 5 | * fourcc.h 6 | * 7 | * This header file declares a set of utility routines for handling 8 | * various graphics formats via their "fourcc" code (a binary string 9 | * representation). 10 | * 11 | * Change History : 12 | * 13 | * $Log$ 14 | * 15 | * 16 | * Copyright Boundary Devices, Inc. 2010 17 | */ 18 | 19 | #include 20 | 21 | inline char const *fourcc_str(unsigned long fcc){ 22 | static char buf[5]; 23 | memcpy(buf,&fcc,sizeof(buf)-1); 24 | buf[4] = '\0' ; 25 | return buf ; 26 | } 27 | 28 | inline unsigned fourcc_from_str(char const *fcc){ 29 | unsigned rval = 0 ; 30 | strncpy((char *)&rval,fcc,sizeof(fcc)); 31 | return rval ; 32 | } 33 | 34 | /* 35 | * This routine converts and validates the specified fourcc 36 | * value 37 | */ 38 | bool supported_fourcc(char const *arg, unsigned &fourcc); 39 | 40 | /* 41 | * Same for binary input 42 | */ 43 | bool supported_fourcc(unsigned fourcc); 44 | 45 | /* 46 | * retrieve the list of supported formats 47 | */ 48 | void supported_fourcc_formats(unsigned const *&values, unsigned &numValues); 49 | 50 | /* 51 | * Return the number of bits per pixel for the supported format. Note that in the 52 | * case of YUV formats, this is the number of bits of Y, not the total number, 53 | * so it can be used in the calculation of fb_var_screeninfo.bits_per_pixel and 54 | * line length. 55 | */ 56 | unsigned bits_per_pixel(unsigned fourcc); 57 | 58 | /* 59 | * Use this to get the size and offsets of the y, u and v portions 60 | * of a YUV image format and the increment between samples of u and v. 61 | * 62 | * Returns false if not a YUV image format. 63 | */ 64 | bool fourccOffsets( 65 | unsigned fourcc, 66 | unsigned width, 67 | unsigned height, 68 | unsigned &ysize, 69 | unsigned &yoffs, 70 | unsigned &yadder, 71 | unsigned &uvsize, 72 | unsigned &uvrowdiv, 73 | unsigned &uvcoldiv, 74 | unsigned &uoffs, 75 | unsigned &voffs, 76 | unsigned &uvadder, 77 | unsigned &totalsize ); 78 | 79 | bool isYUV(unsigned fourcc); 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /hexDump.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module hexDump.cpp 3 | * 4 | * This module defines the methods of the hexDumper_t 5 | * class as declared in hexDump.h 6 | * 7 | * 8 | * Change History : 9 | * 10 | * $Log: hexDump.cpp,v $ 11 | * Revision 1.4 2005-05-25 16:25:04 ericn 12 | * -added address spec 13 | * 14 | * Revision 1.3 2004/07/04 21:31:47 ericn 15 | * -added dumpHex method 16 | * 17 | * Revision 1.2 2004/03/17 04:56:19 ericn 18 | * -updates for mini-board (no sound, video, touch screen) 19 | * 20 | * Revision 1.1 2002/11/11 04:30:45 ericn 21 | * -moved from boundary1 22 | * 23 | * Revision 1.2 2002/11/03 04:29:39 ericn 24 | * -added stand-alone program 25 | * 26 | * Revision 1.1 2002/09/10 14:30:44 ericn 27 | * -Initial import 28 | * 29 | * 30 | * Copyright Boundary Devices, Inc. 2002 31 | */ 32 | 33 | 34 | #include "hexDump.h" 35 | #include 36 | 37 | static const char hexChars[] = { 38 | '0', '1', '2', '3', 39 | '4', '5', '6', '7', 40 | '8', '9', 'A', 'B', 41 | 'C', 'D', 'E', 'F' 42 | }; 43 | 44 | static char *byteOut( char *nextIn, unsigned char b ) 45 | { 46 | *nextIn++ = hexChars[ b >> 4 ]; 47 | *nextIn++ = hexChars[ b & 0x0f ]; 48 | return nextIn ; 49 | } 50 | 51 | static char *longOut( char *nextIn, unsigned long v ) 52 | { 53 | for( unsigned i = 0 ; i < 4 ; i++ ) 54 | { 55 | unsigned char const byte = v >> 24 ; 56 | v <<= 8 ; 57 | nextIn = byteOut( nextIn, byte ); 58 | } 59 | 60 | return nextIn ; 61 | } 62 | 63 | bool hexDumper_t :: nextLine( void ) 64 | { 65 | if( 0 < bytesLeft_ ) 66 | { 67 | char *next = longOut( lineBuf_, (unsigned long)addr_ ); 68 | *next++ = ' ' ; 69 | *next++ = ' ' ; 70 | *next++ = ' ' ; 71 | 72 | unsigned lineBytes = ( 16 < bytesLeft_ ) ? 16 : bytesLeft_ ; 73 | unsigned char *bytes = (unsigned char *)data_ ; 74 | 75 | for( unsigned i = 0 ; i < lineBytes ; i++ ) 76 | { 77 | next = byteOut( next, *bytes++ ); 78 | *next++ = ' ' ; 79 | if( 7 == i ) 80 | { 81 | *next++ = ' ' ; 82 | *next++ = ' ' ; 83 | } 84 | } 85 | 86 | for( unsigned i = lineBytes ; i < 16 ; i++ ) 87 | { 88 | *next++ = ' ' ; 89 | *next++ = ' ' ; 90 | *next++ = ' ' ; 91 | if( 7 == i ) 92 | { 93 | *next++ = ' ' ; 94 | *next++ = ' ' ; 95 | } 96 | } 97 | 98 | *next++ = ' ' ; 99 | *next++ = ' ' ; 100 | 101 | bytes = (unsigned char *)data_ ; 102 | for( unsigned i = 0 ; i < lineBytes ; i++ ) 103 | { 104 | unsigned char c = *bytes++ ; 105 | if( ( ' ' <= c ) && ( '\x7f' > c ) ) 106 | *next++ = c ; 107 | else 108 | *next++ = '.' ; 109 | } 110 | 111 | *next = 0 ; 112 | 113 | data_ = bytes ; 114 | addr_ += lineBytes ; 115 | bytesLeft_ -= lineBytes ; 116 | return true ; 117 | } 118 | else 119 | return false ; 120 | } 121 | 122 | void dumpHex( char const *label, void const *data, unsigned size ) 123 | { 124 | printf( "---> %s\n", label ); 125 | hexDumper_t dump( data, size ); 126 | while( dump.nextLine() ) 127 | printf( "%s\n", dump.getLine() ); 128 | } 129 | 130 | #ifdef __STANDALONE__ 131 | #include 132 | #include 133 | #include 134 | #include 135 | #include 136 | #include 137 | #include 138 | 139 | int main( int argc, char const * const argv[] ) 140 | { 141 | if( 2 == argc ) 142 | { 143 | struct stat st ; 144 | int const statResult = stat( argv[1], &st ); 145 | if( 0 == statResult ) 146 | { 147 | int fd = open( argv[1], O_RDONLY ); 148 | if( 0 <= fd ) 149 | { 150 | off_t const fileSize = lseek( fd, 0, SEEK_END ); 151 | printf( "fileSize: %u\n", fileSize ); 152 | lseek( fd, 0, SEEK_SET ); 153 | void *mem = mmap( 0, fileSize, PROT_READ, MAP_PRIVATE, fd, 0 ); 154 | if( MAP_FAILED != mem ) 155 | { 156 | hexDumper_t dump( mem, fileSize ); 157 | 158 | while( dump.nextLine() ) 159 | printf( "%s\n", dump.getLine() ); 160 | 161 | char inBuf[256]; 162 | fgets( inBuf, sizeof(inBuf), stdin ); 163 | 164 | munmap( mem, fileSize ); 165 | 166 | } // mapped file 167 | else 168 | fprintf( stderr, "Error %m mapping %s\n", argv[1] ); 169 | 170 | close( fd ); 171 | } 172 | else 173 | fprintf( stderr, "Error %m opening %s\n", argv[1] ); 174 | } 175 | else 176 | fprintf( stderr, "Error %m finding %s\n", argv[1] ); 177 | } 178 | else 179 | fprintf( stderr, "Usage : hexDump fileName\n" ); 180 | 181 | return 0 ; 182 | } 183 | #endif 184 | -------------------------------------------------------------------------------- /hexDump.h: -------------------------------------------------------------------------------- 1 | #ifndef __HEXDUMP_H__ 2 | #define __HEXDUMP_H__ "$Id: hexDump.h,v 1.3 2005-05-25 16:25:06 ericn Exp $" 3 | 4 | /* 5 | * hexDump.h 6 | * 7 | * This header file declares the hexDumper_t 8 | * class, which is used for displaying hunks of 9 | * memory for examination. 10 | * 11 | * 12 | * Change History : 13 | * 14 | * $Log: hexDump.h,v $ 15 | * Revision 1.3 2005-05-25 16:25:06 ericn 16 | * -added address spec 17 | * 18 | * Revision 1.2 2004/07/04 21:31:45 ericn 19 | * -added dumpHex method 20 | * 21 | * Revision 1.1 2002/11/11 04:30:45 ericn 22 | * -moved from boundary1 23 | * 24 | * Revision 1.1 2002/09/10 14:30:44 ericn 25 | * -Initial import 26 | * 27 | * 28 | * 29 | * Copyright Boundary Devices, Inc. 2002 30 | */ 31 | 32 | class hexDumper_t { 33 | public: 34 | hexDumper_t( void const *data, 35 | unsigned long size, 36 | unsigned long addr = 0 ) 37 | : data_( data ), 38 | addr_( addr ), 39 | bytesLeft_( size ){} 40 | 41 | // 42 | // returns true and fills in line if something left 43 | // use getLine() and getLineLength() to get the data 44 | // 45 | bool nextLine( void ); 46 | 47 | char const *getLine( void ) const { return lineBuf_ ; } 48 | 49 | private: 50 | void const *data_ ; 51 | unsigned long addr_ ; 52 | unsigned long bytesLeft_ ; 53 | char lineBuf_[ 81 ]; 54 | }; 55 | 56 | // dump to stdout 57 | void dumpHex( char const *label, void const *data, unsigned size ); 58 | 59 | #endif 60 | 61 | -------------------------------------------------------------------------------- /imx_h264_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMX_H264_ENCODER_H__ 2 | #define __IMX_H264_ENCODER_H__ "$Id$" 3 | 4 | /* 5 | * imx_h264_encoder.h 6 | * 7 | * This header file declares the h264_encoder_t class for 8 | * use in encoding YUV data as H264 using the i.MX51's 9 | * hardware encoder. 10 | * 11 | * The simplest use-case is: 12 | * 13 | * initialize 14 | * while (more frames) { 15 | * get_bufs(); 16 | * fill in YUV data 17 | * encode() 18 | * process output data 19 | * } 20 | * 21 | * but this class also supports queueing and asynchronous completion 22 | * of decoding. Using this interface, the simplest use case is 23 | * something like this: 24 | * 25 | * while (more frames) { 26 | * if( get_bufs() ) { 27 | * fill in YUV data 28 | * start_encode() 29 | * } 30 | * if( encode_complete() ) { 31 | * process output data 32 | * } 33 | * ... poll other devices 34 | * } 35 | * 36 | * This queued interface allows tagging of each encode operation with 37 | * an application-defined opaque parameter. It's envisioned that the 38 | * parameter will provide at least timing information about when the 39 | * frame of data was received (from a camera). 40 | * 41 | * Copyright Boundary Devices, Inc. 2010 42 | */ 43 | extern "C" { 44 | #include 45 | #include 46 | }; 47 | 48 | #include "imx_vpu.h" 49 | 50 | class h264_encoder_t { 51 | public: 52 | h264_encoder_t(vpu_t &vpu, 53 | unsigned width, 54 | unsigned height, 55 | unsigned fourcc, 56 | unsigned gopSize, 57 | struct v4l2_buffer *v4lbuffers, 58 | unsigned numBuffers, 59 | unsigned char **buffers); 60 | 61 | bool initialized( void ) const { return initialized_ ; } 62 | 63 | inline unsigned fourcc(void) const { return fourcc_ ; } 64 | inline unsigned width(void) const { return w_ ; } 65 | inline unsigned height(void) const { return h_ ; } 66 | inline unsigned yuvSize(void) const { return imgSize_ ; } 67 | 68 | bool get_bufs( unsigned index, unsigned char *&y, unsigned char *&u, unsigned char *&v ); 69 | 70 | // synchronous encode 71 | bool encode( unsigned index, void const *&outData, unsigned &outLength, bool &iframe); 72 | 73 | // get AVC headers 74 | bool getSPS( void const *&sps, unsigned &len); 75 | bool getPPS( void const *&pps, unsigned &len); 76 | ~h264_encoder_t(void); 77 | private: 78 | #if 0 79 | struct frame_buf { 80 | int addrY; 81 | int addrCb; 82 | int addrCr; 83 | int mvColBuf; 84 | vpu_mem_desc desc; 85 | }; 86 | #endif 87 | 88 | bool initialized_ ; 89 | unsigned fourcc_ ; 90 | unsigned w_ ; 91 | unsigned h_ ; 92 | unsigned imgSize_ ; 93 | EncHandle handle_ ; 94 | PhysicalAddress phy_bsbuf_addr; /* Physical bitstream buffer */ 95 | unsigned virt_bsbuf_addr; /* Virtual bitstream buffer */ 96 | int picwidth; /* Picture width */ 97 | int picheight; /* Picture height */ 98 | unsigned fbcount; /* Total number of framebuffers allocated */ 99 | FrameBuffer *fb; /* frame buffer base given to encoder */ 100 | unsigned char **buffers ; /* mmapped */ 101 | unsigned yoffs ; 102 | unsigned uoffs ; 103 | unsigned voffs ; 104 | void *spsdata ; 105 | unsigned spslen ; 106 | void *ppsdata ; 107 | unsigned ppslen ; 108 | unsigned gopsize ; 109 | unsigned frameidx ; 110 | }; 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /imx_mjpeg_encoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module imx_mjpeg_encoder.cpp 3 | * 4 | * This module defines the methods of the mjpeg_encoder_t class 5 | * as declared in imx_mjpeg_encoder.h 6 | * 7 | * Copyright Boundary Devices, Inc. 2010 8 | */ 9 | 10 | #include "imx_mjpeg_encoder.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #define DEBUGPRINT 16 | #include "debugPrint.h" 17 | #include "fourcc.h" 18 | 19 | #include 20 | #include 21 | 22 | #define STREAM_BUF_SIZE 0x80000 23 | 24 | static unsigned char lumaDcBits[16] = { 25 | 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 26 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 | }; 28 | static unsigned char lumaDcValue[16] = { 29 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 30 | 0x08, 0x09, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 31 | }; 32 | static unsigned char lumaAcBits[16] = { 33 | 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 34 | 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D, 35 | }; 36 | static unsigned char lumaAcValue[168] = { 37 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 38 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 39 | 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 40 | 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 41 | 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 42 | 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 43 | 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 44 | 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 45 | 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 46 | 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 47 | 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 48 | 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 49 | 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 50 | 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 51 | 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 52 | 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 53 | 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 54 | 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 55 | 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 56 | 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 57 | 0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 | }; 59 | static unsigned char chromaDcBits[16] = { 60 | 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 61 | 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 62 | }; 63 | static unsigned char chromaDcValue[16] = { 64 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 65 | 0x08, 0x09, 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 66 | }; 67 | static unsigned char chromaAcBits[16] = { 68 | 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 69 | 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77, 70 | }; 71 | static unsigned char chromaAcValue[168] = { 72 | 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 73 | 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 74 | 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 75 | 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 76 | 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 77 | 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 78 | 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 79 | 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 80 | 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 81 | 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 82 | 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 83 | 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 84 | 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 85 | 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 86 | 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 87 | 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 88 | 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 89 | 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 90 | 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 91 | 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 92 | 0xF9, 0xFA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 93 | }; 94 | static unsigned char lumaQ[64] = { 95 | 0x0C, 0x08, 0x08, 0x08, 0x09, 0x08, 0x0C, 0x09, 96 | 0x09, 0x0C, 0x11, 0x0B, 0x0A, 0x0B, 0x11, 0x15, 97 | 0x0F, 0x0C, 0x0C, 0x0F, 0x15, 0x18, 0x13, 0x13, 98 | 0x15, 0x13, 0x13, 0x18, 0x11, 0x0C, 0x0C, 0x0C, 99 | 0x0C, 0x0C, 0x0C, 0x11, 0x0C, 0x0C, 0x0C, 0x0C, 100 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 101 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 102 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 103 | }; 104 | static unsigned char chromaBQ[64] = { 105 | 0x0D, 0x0B, 0x0B, 0x0D, 0x0E, 0x0D, 0x10, 0x0E, 106 | 0x0E, 0x10, 0x14, 0x0E, 0x0E, 0x0E, 0x14, 0x14, 107 | 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x11, 0x0C, 0x0C, 108 | 0x0C, 0x0C, 0x0C, 0x11, 0x11, 0x0C, 0x0C, 0x0C, 109 | 0x0C, 0x0C, 0x0C, 0x11, 0x0C, 0x0C, 0x0C, 0x0C, 110 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 111 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 112 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 113 | }; 114 | static unsigned char chromaRQ[64] = { 115 | 0x0D, 0x0B, 0x0B, 0x0D, 0x0E, 0x0D, 0x10, 0x0E, 116 | 0x0E, 0x10, 0x14, 0x0E, 0x0E, 0x0E, 0x14, 0x14, 117 | 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x11, 0x0C, 0x0C, 118 | 0x0C, 0x0C, 0x0C, 0x11, 0x11, 0x0C, 0x0C, 0x0C, 119 | 0x0C, 0x0C, 0x0C, 0x11, 0x0C, 0x0C, 0x0C, 0x0C, 120 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 121 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 122 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 123 | }; 124 | static unsigned char lumaQ2[64] = { 125 | 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05, 126 | 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0B, 127 | 0x08, 0x06, 0x06, 0x08, 0x0B, 0x0C, 0x0A, 0x0A, 128 | 0x0B, 0x0A, 0x0A, 0x0C, 0x10, 0x0C, 0x0C, 0x0C, 129 | 0x0C, 0x0C, 0x0C, 0x10, 0x0C, 0x0C, 0x0C, 0x0C, 130 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 131 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 132 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 133 | }; 134 | static unsigned char chromaBQ2[64] = { 135 | 0x07, 0x07, 0x07, 0x0D, 0x0C, 0x0D, 0x18, 0x10, 136 | 0x10, 0x18, 0x14, 0x0E, 0x0E, 0x0E, 0x14, 0x14, 137 | 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x11, 0x0C, 0x0C, 138 | 0x0C, 0x0C, 0x0C, 0x11, 0x11, 0x0C, 0x0C, 0x0C, 139 | 0x0C, 0x0C, 0x0C, 0x11, 0x0C, 0x0C, 0x0C, 0x0C, 140 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 141 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 142 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 143 | }; 144 | static unsigned char chromaRQ2[64] = { 145 | 0x07, 0x07, 0x07, 0x0D, 0x0C, 0x0D, 0x18, 0x10, 146 | 0x10, 0x18, 0x14, 0x0E, 0x0E, 0x0E, 0x14, 0x14, 147 | 0x0E, 0x0E, 0x0E, 0x0E, 0x14, 0x11, 0x0C, 0x0C, 148 | 0x0C, 0x0C, 0x0C, 0x11, 0x11, 0x0C, 0x0C, 0x0C, 149 | 0x0C, 0x0C, 0x0C, 0x11, 0x0C, 0x0C, 0x0C, 0x0C, 150 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 151 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 152 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 153 | }; 154 | 155 | mjpeg_encoder_t::mjpeg_encoder_t( 156 | vpu_t &vpu, 157 | unsigned w, 158 | unsigned h, 159 | unsigned fourcc, 160 | int fdCamera, 161 | unsigned numBuffers, 162 | unsigned char **cameraBuffers) 163 | : initialized_(false) 164 | , fourcc_(fourcc) 165 | , w_(w) 166 | , h_(h) 167 | , imgSize_(0) 168 | , handle_(0) 169 | , buffers(cameraBuffers) 170 | , yoffs(0) 171 | , uoffs(0) 172 | , voffs(0) 173 | { 174 | if( (0 == w) || (0 == h) ) { 175 | fprintf(stderr, "Invalid w or h (%ux%u)\n", w, h ); 176 | return ; 177 | } 178 | fprintf(stderr, "%s: %ux%u - %u buffers\n", __func__, w_, h_, numBuffers ); 179 | vpu_mem_desc mem_desc = {0}; 180 | 181 | unsigned ysize ; 182 | unsigned yadder ; 183 | unsigned uvsize ; 184 | unsigned uvrowdiv ; 185 | unsigned uvcoldiv ; 186 | unsigned uvadder ; 187 | unsigned totalsize ; 188 | if( !fourccOffsets(fourcc,w,h,ysize,yoffs,yadder,uvsize,uvrowdiv,uvcoldiv,uoffs,voffs,uvadder,totalsize) ){ 189 | fprintf(stderr, "Invalid fourcc 0x%x\n", fourcc); 190 | return ; 191 | } 192 | imgSize_ = totalsize ; 193 | 194 | printf( "%s: fourcc offsets %u/%u/%u, adders %u/%u\n", __func__, yoffs, uoffs,voffs, yadder,uvadder); 195 | printf( "%s: sizes %u/%u: %u\n", __func__, ysize, uvsize, totalsize); 196 | 197 | /* get physical contigous bit stream buffer */ 198 | mem_desc.size = STREAM_BUF_SIZE; 199 | if (0 != IOGetPhyMem(&mem_desc)) { 200 | fprintf(stderr,"Unable to obtain physical memory\n"); 201 | return ; 202 | } 203 | 204 | /* mmap that physical buffer */ 205 | virt_bsbuf_addr = IOGetVirtMem(&mem_desc); 206 | if (virt_bsbuf_addr <= 0) { 207 | fprintf(stderr,"Unable to map physical memory\n"); 208 | IOFreePhyMem(&mem_desc); 209 | return ; 210 | } 211 | 212 | debugPrint( "stream buffer: %u bytes: phys 0x%lx, cpu 0x%lx, virt 0x%lx (%x)\n", 213 | mem_desc.size, mem_desc.phy_addr, mem_desc.cpu_addr, mem_desc.virt_uaddr, virt_bsbuf_addr ); 214 | 215 | phy_bsbuf_addr = mem_desc.phy_addr; 216 | 217 | EncOpenParam encop = {0}; 218 | /* Fill up parameters for encoding */ 219 | encop.bitstreamBuffer = phy_bsbuf_addr; 220 | encop.bitstreamBufferSize = STREAM_BUF_SIZE; 221 | encop.bitstreamFormat = STD_MJPG ; 222 | 223 | encop.picWidth = picwidth = w; 224 | encop.picHeight = picheight = h; 225 | 226 | /*Note: Frame rate cannot be less than 15fps per H.263 spec */ 227 | encop.frameRateInfo = 30; 228 | encop.bitRate = 0 ; 229 | encop.gopSize = 1 ; 230 | encop.slicemode.sliceMode = 0; /* 0: 1 slice per picture; 1: Multiple slices per picture */ 231 | encop.slicemode.sliceSizeMode = 0; /* 0: silceSize defined by bits; 1: sliceSize defined by MB number*/ 232 | encop.slicemode.sliceSize = 4000; /* Size of a slice in bits or MB numbers */ 233 | 234 | encop.initialDelay = 0; 235 | encop.vbvBufferSize = 0; /* 0 = ignore 8 */ 236 | encop.intraRefresh = 0; 237 | encop.sliceReport = 0; 238 | encop.mbReport = 0; 239 | encop.mbQpReport = 0; 240 | encop.rcIntraQp = -1; 241 | encop.userQpMax = 0; 242 | encop.userGamma = (Uint32)(0.75*32768); /* (0*32768 <= gamma <= 1*32768) */ 243 | encop.RcIntervalMode= 1; /* 0:normal, 1:frame_level, 2:slice_level, 3: user defined Mb_level */ 244 | encop.MbInterval = 0; 245 | 246 | if (uvsize == ysize/2) { 247 | encop.EncStdParam.mjpgParam.mjpg_sourceFormat = 1 ; // YUV422 horizontal 248 | } else if (uvsize == ysize/4) { 249 | encop.EncStdParam.mjpgParam.mjpg_sourceFormat = 0 ; // YUV420 250 | } else 251 | printf( "%s: unknown input format: %u/%u\n", __func__,ysize,uvsize ); 252 | printf( "%s: mjpg_source format %d\n", __func__, encop.EncStdParam.mjpgParam.mjpg_sourceFormat); 253 | encop.ringBufferEnable = 0; 254 | encop.dynamicAllocEnable = 0; 255 | encop.chromaInterleave = (uoffs < voffs) ? (uoffs+uvsize > voffs) 256 | : (voffs+uvsize > uoffs); 257 | printf( "%s: chroma interleaved: %d\n", __func__, encop.chromaInterleave); 258 | Uint8 *qMatTable = encop.EncStdParam.mjpgParam.mjpg_qMatTable = (Uint8*)calloc(192,1); 259 | if (qMatTable == NULL) { 260 | fprintf(stderr,"Failed to allocate qMatTable\n"); 261 | IOFreePhyMem(&mem_desc); 262 | return ; 263 | } 264 | 265 | /* Rearrange and insert pre-defined Q-matrix to deticated variable. */ 266 | for(int i = 0; i < 64; i += 4) 267 | { 268 | qMatTable[i] = lumaQ2[i + 3]; 269 | qMatTable[i + 1] = lumaQ2[i + 2]; 270 | qMatTable[i + 2] = lumaQ2[i + 1]; 271 | qMatTable[i + 3] = lumaQ2[i]; 272 | } 273 | 274 | for(int i = 64; i < 128; i += 4) 275 | { 276 | qMatTable[i] = chromaBQ2[i + 3 - 64]; 277 | qMatTable[i + 1] = chromaBQ2[i + 2 - 64]; 278 | qMatTable[i + 2] = chromaBQ2[i + 1 - 64]; 279 | qMatTable[i + 3] = chromaBQ2[i - 64]; 280 | } 281 | 282 | for(int i = 128; i < 192; i += 4) 283 | { 284 | qMatTable[i] = chromaRQ2[i + 3 - 128]; 285 | qMatTable[i + 1] = chromaRQ2[i + 2 - 128]; 286 | qMatTable[i + 2] = chromaRQ2[i + 1 - 128]; 287 | qMatTable[i + 3] = chromaRQ2[i - 128]; 288 | } 289 | 290 | unsigned char *huffTable = encop.EncStdParam.mjpgParam.mjpg_hufTable = (Uint8*)calloc(432,1); 291 | if (huffTable == NULL) { 292 | free(qMatTable); 293 | fprintf(stderr,"Failed to allocate huffTable\n"); 294 | IOFreePhyMem(&mem_desc); 295 | return ; 296 | } 297 | 298 | debugPrint("allocated qMat and huff tables\n"); 299 | /* Don't consider user defined hufftable this time */ 300 | /* Rearrange and insert pre-defined Huffman table to deticated variable. */ 301 | for(int i = 0; i < 16; i += 4) 302 | { 303 | huffTable[i] = lumaDcBits[i + 3]; 304 | huffTable[i + 1] = lumaDcBits[i + 2]; 305 | huffTable[i + 2] = lumaDcBits[i + 1]; 306 | huffTable[i + 3] = lumaDcBits[i]; 307 | } 308 | for(int i = 16; i < 32 ; i += 4) 309 | { 310 | huffTable[i] = lumaDcValue[i + 3 - 16]; 311 | huffTable[i + 1] = lumaDcValue[i + 2 - 16]; 312 | huffTable[i + 2] = lumaDcValue[i + 1 - 16]; 313 | huffTable[i + 3] = lumaDcValue[i - 16]; 314 | } 315 | for(int i = 32; i < 48; i += 4) 316 | { 317 | huffTable[i] = lumaAcBits[i + 3 - 32]; 318 | huffTable[i + 1] = lumaAcBits[i + 2 - 32]; 319 | huffTable[i + 2] = lumaAcBits[i + 1 - 32]; 320 | huffTable[i + 3] = lumaAcBits[i - 32]; 321 | } 322 | for(int i = 48; i < 216; i += 4) 323 | { 324 | huffTable[i] = lumaAcValue[i + 3 - 48]; 325 | huffTable[i + 1] = lumaAcValue[i + 2 - 48]; 326 | huffTable[i + 2] = lumaAcValue[i + 1 - 48]; 327 | huffTable[i + 3] = lumaAcValue[i - 48]; 328 | } 329 | for(int i = 216; i < 232; i += 4) 330 | { 331 | huffTable[i] = chromaDcBits[i + 3 - 216]; 332 | huffTable[i + 1] = chromaDcBits[i + 2 - 216]; 333 | huffTable[i + 2] = chromaDcBits[i + 1 - 216]; 334 | huffTable[i + 3] = chromaDcBits[i - 216]; 335 | } 336 | for(int i = 232; i < 248; i += 4) 337 | { 338 | huffTable[i] = chromaDcValue[i + 3 - 232]; 339 | huffTable[i + 1] = chromaDcValue[i + 2 - 232]; 340 | huffTable[i + 2] = chromaDcValue[i + 1 - 232]; 341 | huffTable[i + 3] = chromaDcValue[i - 232]; 342 | } 343 | for(int i = 248; i < 264; i += 4) 344 | { 345 | huffTable[i] = chromaAcBits[i + 3 - 248]; 346 | huffTable[i + 1] = chromaAcBits[i + 2 - 248]; 347 | huffTable[i + 2] = chromaAcBits[i + 1 - 248]; 348 | huffTable[i + 3] = chromaAcBits[i - 248]; 349 | } 350 | for(int i = 264; i < 432; i += 4) 351 | { 352 | huffTable[i] = chromaAcValue[i + 3 - 264]; 353 | huffTable[i + 1] = chromaAcValue[i + 2 - 264]; 354 | huffTable[i + 2] = chromaAcValue[i + 1 - 264]; 355 | huffTable[i + 3] = chromaAcValue[i - 264]; 356 | } 357 | 358 | debugPrint("check open params\n"); 359 | 360 | if (encop.bitstreamBuffer % 4) { /* not 4-bit aligned */ 361 | printf( "--> bitstreamBuffer %lx\n", encop.bitstreamBuffer); 362 | } 363 | if (encop.bitstreamBufferSize % 1024 || 364 | encop.bitstreamBufferSize < 1024 || 365 | encop.bitstreamBufferSize > 16383 * 1024) { 366 | printf( "--> bitstreamBufferSize %ld\n", encop.bitstreamBufferSize); 367 | } 368 | if (encop.bitstreamFormat != STD_MPEG4 && 369 | encop.bitstreamFormat != STD_H263 && 370 | encop.bitstreamFormat != STD_AVC && 371 | encop.bitstreamFormat != STD_MJPG) { 372 | printf( "--> bitstreamFormat %x\n", encop.bitstreamFormat); 373 | } 374 | if (encop.bitRate > 32767 || encop.bitRate < 0) { 375 | printf( "--> bitrate %d\n", encop.bitRate); 376 | } 377 | if (encop.bitRate != 0 && encop.initialDelay > 32767) { 378 | printf( "--> bitrate %d, initial delay %d\n", encop.bitRate, encop.initialDelay); 379 | } 380 | if (encop.bitRate != 0 && encop.initialDelay != 0 && 381 | encop.vbvBufferSize < 0) { 382 | printf( "--> bitrate %d, initial delay %d, vbvBufferSize %d\n", encop.bitRate, encop.initialDelay, encop.vbvBufferSize ); 383 | } 384 | if (encop.gopSize > 60) { 385 | printf( "--> gopSize %d\n", encop.gopSize ); 386 | } 387 | if (encop.slicemode.sliceMode != 0 && encop.slicemode.sliceMode != 1) { 388 | printf( "--> sliceMode %d\n", encop.slicemode.sliceMode ); 389 | } 390 | if (encop.slicemode.sliceMode == 1) { 391 | if (encop.slicemode.sliceSizeMode != 0 && 392 | encop.slicemode.sliceSizeMode != 1) { 393 | printf( "--> slicemode.sliceSizeMode %d\n", encop.slicemode.sliceSizeMode ); 394 | } 395 | if (encop.slicemode.sliceSize == 0) { 396 | printf( "--> slicemode.sliceSize %d\n", encop.slicemode.sliceSize ); 397 | } 398 | } 399 | if (cpu_is_mx27()) { 400 | if (encop.sliceReport != 0 && encop.sliceReport != 1) { 401 | printf( "--> sliceReport %d\n", encop.sliceReport ); 402 | } 403 | if (encop.mbReport != 0 && encop.mbReport != 1) { 404 | printf( "--> mbReport %d\n", encop.mbReport ); 405 | } 406 | } 407 | if (encop.intraRefresh < 0 || encop.intraRefresh >= 408 | (encop.picWidth * encop.picHeight / 256)) { 409 | debugPrint( "--> intraRefresh %d, width %d, height %d\n", encop.intraRefresh, encop.picWidth, encop.picHeight ); 410 | } 411 | 412 | debugPrint( "format %d, %ux%u\n", encop.bitstreamFormat, encop.picWidth, encop.picHeight ); 413 | 414 | if (encop.picWidth < 32 || encop.picHeight < 16) { 415 | debugPrint( "bad size\n"); 416 | } 417 | 418 | debugPrint( "opening encoder\n" ); 419 | 420 | RetCode ret = vpu_EncOpen(&handle_, &encop); 421 | if (ret != RETCODE_SUCCESS) { 422 | fprintf(stderr,"Encoder open failed %d\n", ret); 423 | IOFreePhyMem(&mem_desc); 424 | return ; 425 | } 426 | 427 | debugPrint( "encoder initialized\n" ); 428 | 429 | SearchRamParam search_pa = {0}; 430 | iram_t iram; 431 | int ram_size; 432 | 433 | memset(&iram, 0, sizeof(iram_t)); 434 | ram_size = ((picwidth + 15) & ~15) * 36 + 2048; 435 | IOGetIramBase(&iram); 436 | if ((iram.end - iram.start) < ram_size) { 437 | debugPrint("vpu iram is less than needed: %u..%u/%u\n", iram.start,iram.end,ram_size); 438 | debugPrint("NOT Using IRAM for ME\n" ); 439 | } else { 440 | /* Allocate max iram for vpu encoder search ram*/ 441 | ram_size = iram.end - iram.start; 442 | search_pa.searchRamAddr = iram.start; 443 | search_pa.SearchRamSize = ram_size; 444 | debugPrint( "search iram %u..%u for %u bytes\n", iram.start, iram.end, ram_size ); 445 | ret = vpu_EncGiveCommand(handle_, ENC_SET_SEARCHRAM_PARAM, &search_pa); 446 | if (ret != RETCODE_SUCCESS) { 447 | fprintf(stderr, "Encoder SET_SEARCHRAM_PARAM failed\n"); 448 | IOFreePhyMem(&mem_desc); 449 | return ; 450 | } 451 | else { 452 | debugPrint("Using IRAM for ME\n" ); 453 | } 454 | } 455 | 456 | debugPrint( "get initial info\n"); 457 | EncInitialInfo initinfo = {0}; 458 | ret = vpu_EncGetInitialInfo(handle_, &initinfo); 459 | if (ret != RETCODE_SUCCESS) { 460 | fprintf(stderr,"Encoder GetInitialInfo failed\n"); 461 | IOFreePhyMem(&mem_desc); 462 | return ; 463 | } 464 | 465 | debugPrint( "have initial info\n" ); 466 | 467 | fbcount = numBuffers ; 468 | int stride = ((picwidth + 15) & ~15)*((0 != encop.EncStdParam.mjpgParam.mjpg_sourceFormat)+1); 469 | 470 | fb = (FrameBuffer *)calloc(fbcount, sizeof(FrameBuffer)); 471 | if (fb == NULL) { 472 | fprintf(stderr,"Failed to allocate fb\n"); 473 | IOFreePhyMem(&mem_desc); 474 | return ; 475 | } 476 | debugPrint( "allocated FrameBuffer fb: %p\n", fb ); 477 | 478 | for (int i = 0; i < fbcount; i++) { 479 | struct v4l2_buffer buf ; memset(&buf,0,sizeof(buf)); 480 | 481 | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 482 | buf.memory = V4L2_MEMORY_MMAP; 483 | buf.index = i ; 484 | 485 | if (0 > ioctl (fdCamera, VIDIOC_QUERYBUF, &buf)) { 486 | perror ("VIDIOC_QUERYBUF"); 487 | free(fb); 488 | IOFreePhyMem(&mem_desc); 489 | return ; 490 | } 491 | fb[i].bufY = buf.m.offset+yoffs; 492 | fb[i].bufCb = buf.m.offset+uoffs; 493 | fb[i].bufCr = buf.m.offset+voffs; 494 | } 495 | debugPrint( "registering frame buffer\n" ); 496 | ret = vpu_EncRegisterFrameBuffer(handle_, fb, fbcount, stride, stride); 497 | if (ret != RETCODE_SUCCESS) { 498 | fprintf(stderr,"Register frame buffer failed\n"); 499 | free(fb); 500 | IOFreePhyMem(&mem_desc); 501 | return ; 502 | } 503 | else 504 | debugPrint( "registered frame buffer\n" ); 505 | 506 | debugPrint( "%u frame buffers allocated and registered\n", fbcount ); 507 | 508 | debugPrint( "freeing huffTable and qMatTable\n" ); 509 | if (huffTable) 510 | free(huffTable); 511 | if (qMatTable) 512 | free(qMatTable); 513 | initialized_ = true ; 514 | debugPrint("Done with %s\n", __func__ ); 515 | } 516 | 517 | mjpeg_encoder_t::~mjpeg_encoder_t(void) { 518 | 519 | debugPrint( "closing encoder\n" ); 520 | RetCode rc = vpu_EncClose(handle_); 521 | if( RETCODE_SUCCESS != rc ) 522 | fprintf(stderr, "Error %d closing encoder\n", rc ); 523 | else { 524 | debugPrint( "encoder closed\n" ); 525 | } 526 | } 527 | 528 | bool mjpeg_encoder_t::get_bufs( unsigned index, unsigned char *&y, unsigned char *&u, unsigned char *&v ) 529 | { 530 | unsigned char *base = buffers[index]; 531 | y = base + yoffs ; 532 | u = base + uoffs ; 533 | v = base + voffs ; 534 | return true ; 535 | } 536 | 537 | bool mjpeg_encoder_t::encode(unsigned index, void const *&outData, unsigned &outLength) 538 | { 539 | EncParam enc_param = {0}; 540 | 541 | enc_param.sourceFrame = &fb[index]; 542 | enc_param.quantParam = 23; 543 | enc_param.forceIPicture = 0; 544 | enc_param.skipPicture = 0; 545 | RetCode ret = vpu_EncStartOneFrame(handle_, &enc_param); 546 | if (ret != RETCODE_SUCCESS) { 547 | fprintf(stderr,"vpu_EncStartOneFrame failed Err code:%d\n", 548 | ret); 549 | return false ; 550 | } 551 | 552 | while (vpu_IsBusy()) { 553 | vpu_WaitForInt(30); 554 | if(vpu_IsBusy()){ 555 | debugPrint( "busy\n"); 556 | } 557 | } 558 | 559 | EncOutputInfo outinfo = {0}; 560 | ret = vpu_EncGetOutputInfo(handle_, &outinfo); 561 | if (ret != RETCODE_SUCCESS) { 562 | fprintf(stderr,"vpu_EncGetOutputInfo failed Err code: %d\n", 563 | ret); 564 | return false ; 565 | } 566 | 567 | outData = (void *)(virt_bsbuf_addr + outinfo.bitstreamBuffer - phy_bsbuf_addr); 568 | outLength = outinfo.bitstreamSize ; 569 | return true ; 570 | } 571 | -------------------------------------------------------------------------------- /imx_mjpeg_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMX_MJPEG_ENCODER_H__ 2 | #define __IMX_MJPEG_ENCODER_H__ "$Id$" 3 | 4 | /* 5 | * imx_mjpeg_encoder.h 6 | * 7 | * This header file declares the mjpeg_encoder_t class for 8 | * use in encoding YUV data as MJPEG using the i.MX51's 9 | * hardware encoder. 10 | * 11 | * The simplest use-case is: 12 | * 13 | * initialize 14 | * while (more frames) { 15 | * get_bufs(); 16 | * fill in YUV data 17 | * encode() 18 | * process output data 19 | * } 20 | * 21 | * but this class also supports queueing and asynchronous completion 22 | * of decoding. Using this interface, the simplest use case is 23 | * something like this: 24 | * 25 | * while (more frames) { 26 | * if( get_bufs() ) { 27 | * fill in YUV data 28 | * start_encode() 29 | * } 30 | * if( encode_complete() ) { 31 | * process output data 32 | * } 33 | * ... poll other devices 34 | * } 35 | * 36 | * This queued interface allows tagging of each encode operation with 37 | * an application-defined opaque parameter. It's envisioned that the 38 | * parameter will provide at least timing information about when the 39 | * frame of data was received (from a camera). 40 | * 41 | * Copyright Boundary Devices, Inc. 2010 42 | */ 43 | extern "C" { 44 | #include 45 | #include 46 | }; 47 | 48 | #include "imx_vpu.h" 49 | 50 | class mjpeg_encoder_t { 51 | public: 52 | mjpeg_encoder_t(vpu_t &vpu, 53 | unsigned width, 54 | unsigned height, 55 | unsigned fourcc, 56 | int fdCamera, 57 | unsigned numBuffers, 58 | unsigned char **buffers); 59 | 60 | bool initialized( void ) const { return initialized_ ; } 61 | 62 | inline unsigned fourcc(void) const { return fourcc_ ; } 63 | inline unsigned width(void) const { return w_ ; } 64 | inline unsigned height(void) const { return h_ ; } 65 | inline unsigned yuvSize(void) const { return imgSize_ ; } 66 | 67 | bool get_bufs( unsigned index, unsigned char *&y, unsigned char *&u, unsigned char *&v ); 68 | 69 | // synchronous encode 70 | bool encode( unsigned index, void const *&outData, unsigned &outLength); 71 | 72 | ~mjpeg_encoder_t(void); 73 | private: 74 | #if 0 75 | struct frame_buf { 76 | int addrY; 77 | int addrCb; 78 | int addrCr; 79 | int mvColBuf; 80 | vpu_mem_desc desc; 81 | }; 82 | #endif 83 | 84 | bool initialized_ ; 85 | unsigned fourcc_ ; 86 | unsigned w_ ; 87 | unsigned h_ ; 88 | unsigned imgSize_ ; 89 | EncHandle handle_ ; 90 | PhysicalAddress phy_bsbuf_addr; /* Physical bitstream buffer */ 91 | unsigned virt_bsbuf_addr; /* Virtual bitstream buffer */ 92 | int picwidth; /* Picture width */ 93 | int picheight; /* Picture height */ 94 | unsigned fbcount; /* Total number of framebuffers allocated */ 95 | FrameBuffer *fb; /* frame buffer base given to encoder */ 96 | unsigned char **buffers ; /* mmapped */ 97 | unsigned yoffs ; 98 | unsigned uoffs ; 99 | unsigned voffs ; 100 | }; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /imx_mpeg4_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMX_MPEG4_ENCODER_H__ 2 | #define __IMX_MPEG4_ENCODER_H__ "$Id$" 3 | 4 | /* 5 | * imx_mpeg4_encoder.h 6 | * 7 | * This header file declares the mpeg4_encoder_t class for 8 | * use in encoding YUV data as MPEG4 using the i.MX51's 9 | * hardware encoder. 10 | * 11 | * The simplest use-case is: 12 | * 13 | * initialize 14 | * while (more frames) { 15 | * get_bufs(); 16 | * fill in YUV data 17 | * encode() 18 | * process output data 19 | * } 20 | * 21 | * but this class also supports queueing and asynchronous completion 22 | * of decoding. Using this interface, the simplest use case is 23 | * something like this: 24 | * 25 | * while (more frames) { 26 | * if( get_bufs() ) { 27 | * fill in YUV data 28 | * start_encode() 29 | * } 30 | * if( encode_complete() ) { 31 | * process output data 32 | * } 33 | * ... poll other devices 34 | * } 35 | * 36 | * This queued interface allows tagging of each encode operation with 37 | * an application-defined opaque parameter. It's envisioned that the 38 | * parameter will provide at least timing information about when the 39 | * frame of data was received (from a camera). 40 | * 41 | * Copyright Boundary Devices, Inc. 2010 42 | */ 43 | extern "C" { 44 | #include 45 | #include 46 | }; 47 | 48 | #include "imx_vpu.h" 49 | 50 | class mpeg4_encoder_t { 51 | public: 52 | mpeg4_encoder_t(vpu_t &vpu, 53 | unsigned width, 54 | unsigned height, 55 | unsigned fourcc, 56 | unsigned gopSize, 57 | struct v4l2_buffer *v4lbuffers, 58 | unsigned numBuffers, 59 | unsigned char **buffers); 60 | 61 | bool initialized( void ) const { return initialized_ ; } 62 | 63 | inline unsigned fourcc(void) const { return fourcc_ ; } 64 | inline unsigned width(void) const { return w_ ; } 65 | inline unsigned height(void) const { return h_ ; } 66 | inline unsigned yuvSize(void) const { return imgSize_ ; } 67 | 68 | bool get_bufs( unsigned index, unsigned char *&y, unsigned char *&u, unsigned char *&v ); 69 | 70 | // synchronous encode 71 | bool encode( unsigned index, void const *&outData, unsigned &outLength); 72 | 73 | // get AVC headers 74 | bool getSPS( void const *&sps, unsigned &len); 75 | bool getPPS( void const *&pps, unsigned &len); 76 | ~mpeg4_encoder_t(void); 77 | private: 78 | #if 0 79 | struct frame_buf { 80 | int addrY; 81 | int addrCb; 82 | int addrCr; 83 | int mvColBuf; 84 | vpu_mem_desc desc; 85 | }; 86 | #endif 87 | 88 | bool initialized_ ; 89 | unsigned fourcc_ ; 90 | unsigned w_ ; 91 | unsigned h_ ; 92 | unsigned imgSize_ ; 93 | EncHandle handle_ ; 94 | PhysicalAddress phy_bsbuf_addr; /* Physical bitstream buffer */ 95 | unsigned virt_bsbuf_addr; /* Virtual bitstream buffer */ 96 | int picwidth; /* Picture width */ 97 | int picheight; /* Picture height */ 98 | unsigned fbcount; /* Total number of framebuffers allocated */ 99 | FrameBuffer *fb; /* frame buffer base given to encoder */ 100 | unsigned char **buffers ; /* mmapped */ 101 | unsigned yoffs ; 102 | unsigned uoffs ; 103 | unsigned voffs ; 104 | void *spsdata ; 105 | unsigned spslen ; 106 | void *ppsdata ; 107 | unsigned ppslen ; 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /imx_vpu.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module imx_vpu.cpp 3 | * 4 | * This module defines the methods of the vpu_t class 5 | * as declared in imx_vpu.h 6 | * 7 | * Copyright Boundary Devices, Inc. 2010 8 | */ 9 | 10 | 11 | #include "imx_vpu.h" 12 | #include 13 | extern "C" { 14 | #include 15 | #include 16 | }; 17 | 18 | vpu_t::vpu_t(void) 19 | : worked_( false ) 20 | { 21 | RetCode rc = vpu_Init(0); 22 | worked_ = (RETCODE_SUCCESS == rc); 23 | if( !worked_ ) 24 | fprintf(stderr, "Error %d initializing VPU\n", rc ); 25 | } 26 | 27 | vpu_t::~vpu_t(void) 28 | { 29 | if( worked_ ) { 30 | vpu_UnInit(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /imx_vpu.h: -------------------------------------------------------------------------------- 1 | #ifndef __IMX_VPU_H__ 2 | #define __IMX_VPU_H__ "$Id$" 3 | 4 | /* 5 | * imx_vpu.h 6 | * 7 | * This header file declares the imx_vpu_t class, which 8 | * takes care of initializing the vpu library. 9 | * 10 | * Copyright Boundary Devices, Inc. 2010 11 | */ 12 | 13 | class vpu_t { 14 | public: 15 | vpu_t(void); 16 | ~vpu_t(void); 17 | 18 | bool worked(void) const { return worked_ ; } 19 | private: 20 | bool worked_ ; 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /inputRead.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main( int argc, char const * const argv[] ) 14 | { 15 | struct pollfd fd ; 16 | fd.fd = open(argv[1], O_RDONLY); 17 | fd.events = POLLIN ; 18 | 19 | int doit = 1 ; 20 | ioctl( fd.fd, O_NONBLOCK, &doit ); 21 | 22 | int x ; 23 | int y ; 24 | int touched = 0 ; 25 | int device_id = -1 ; 26 | while (0 < poll(&fd, 1,- 1U)) { 27 | struct input_event event ; 28 | int numRead ; 29 | while (sizeof(event) == (numRead=read(fd.fd,&event,sizeof(event)))){ 30 | printf( "%x:%x:%x\n", event.type, event.code, event.value); 31 | fflush(stdout); 32 | if (EV_ABS == event.type) { 33 | if (ABS_X == event.code) 34 | x = event.value ; 35 | else if (ABS_Y == event.code) { 36 | y = event.value ; 37 | } 38 | else if (ABS_PRESSURE == event.code) { 39 | touched = (0 != event.value); 40 | } 41 | else { 42 | printf( "ABS:%x:%x:%x\n", event.type, event.code, event.value); 43 | fflush(stdout); 44 | } 45 | } 46 | else if (EV_KEY == event.type) { 47 | if (BTN_TOUCH == event.code) { 48 | if (0 == event.value) { 49 | printf("release\n"); 50 | fflush(stdout); 51 | } else { 52 | printf("touch(%d) %3d\t%3d\n", device_id, x, y ); 53 | fflush(stdout); 54 | } 55 | } else{ 56 | printf ("key(0x%x/0x%d)\n", event.code, event.value); 57 | fflush(stdout); 58 | } 59 | } 60 | else if (EV_SYN == event.type) { 61 | if (touched) { 62 | printf("touched(%d) %3d\t%3d\n", device_id, x, y ); 63 | fflush(stdout); 64 | } 65 | } else{ 66 | printf( "unrecognized event 0x%x\n", event.type); 67 | fflush(stdout); 68 | } 69 | } 70 | } 71 | 72 | return 0 ; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /input_mt_read.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ 14 | #define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ 15 | #define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ 16 | #define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ 17 | #define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ 18 | #define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */ 19 | #define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */ 20 | #define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ 21 | #define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ 22 | #define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ 23 | #define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ 24 | #define SYN_MT_REPORT 2 25 | 26 | static char const *typeName(unsigned type) 27 | { 28 | if (EV_SYN==type) { 29 | return " SYN" ; 30 | } else if (EV_ABS==type) { 31 | return " ABS" ; 32 | } else { 33 | static char temp[8]; 34 | snprintf(temp,sizeof(temp),"0x%02x",type); 35 | return temp ; 36 | } 37 | } 38 | 39 | static char const *codeName(unsigned type, unsigned code) { 40 | if (EV_ABS == type) { 41 | if (ABS_MT_TOUCH_MAJOR == code) { 42 | return "MAJOR" ; 43 | } 44 | else if (ABS_MT_TOUCH_MINOR == code) { 45 | return "MINOR" ; 46 | } 47 | else if (ABS_MT_WIDTH_MAJOR == code) { 48 | return "WIDTH_MAJOR" ; 49 | } 50 | else if (ABS_MT_WIDTH_MINOR == code) { 51 | return "WIDTH_MINOR" ; 52 | } 53 | else if (ABS_MT_ORIENTATION == code) { 54 | return "ORIENTATION" ; 55 | } 56 | else if (ABS_MT_POSITION_X == code) { 57 | return "POS_X" ; 58 | } 59 | else if (ABS_MT_POSITION_Y == code) { 60 | return "POS_Y" ; 61 | } 62 | else if (ABS_MT_TOOL_TYPE == code) { 63 | return "TOOL_TYPE" ; 64 | } 65 | else if (ABS_MT_BLOB_ID == code) { 66 | return "BLOB_ID" ; 67 | } 68 | else if (ABS_MT_TRACKING_ID == code) { 69 | return "TRACKING_ID" ; 70 | } 71 | } else if (EV_SYN == type) { 72 | if (SYN_MT_REPORT==code) { 73 | return "MT_REPORT" ; 74 | } else if (SYN_REPORT==code) { 75 | return "SYNC" ; 76 | } 77 | } 78 | 79 | static char temp[8]; 80 | snprintf(temp,sizeof(temp),"0x%04x", code); 81 | return temp ; 82 | } 83 | 84 | int main( int argc, char const * const argv[] ) 85 | { 86 | struct pollfd fd ; 87 | fd.fd = open(argv[1], O_RDONLY); 88 | fd.events = POLLIN ; 89 | 90 | int doit = 1 ; 91 | ioctl( fd.fd, O_NONBLOCK, &doit ); 92 | 93 | while (0 < poll(&fd, 1,- 1U)) { 94 | struct input_event event ; 95 | int numRead ; 96 | while (sizeof(event) == (numRead=read(fd.fd,&event,sizeof(event)))){ 97 | printf("type %s\tcode %s\tvalue 0x%04x\n", typeName(event.type),codeName(event.type,event.code),event.value); 98 | } 99 | } 100 | 101 | return 0 ; 102 | } 103 | 104 | -------------------------------------------------------------------------------- /inputattach.c: -------------------------------------------------------------------------------- 1 | /* 2 | * $Id: inputattach.c,v 1.24 2006/02/08 12:19:31 vojtech Exp $ 3 | * 4 | * Copyright (c) 1999-2000 Vojtech Pavlik 5 | * 6 | * Sponsored by SuSE 7 | * 8 | * Twiddler support Copyright (c) 2001 Arndt Schoenewald 9 | * Sponsored by Quelltext AG (http://www.quelltext-ag.de), Dortmund, Germany 10 | * 11 | * Sahara Touchit-213 mode added by Claudio Nieder 2008-05-01. 12 | */ 13 | 14 | /* 15 | * Input line discipline attach program 16 | */ 17 | 18 | /* 19 | * This program is free software; you can redistribute it and/or modify 20 | * it under the terms of the GNU General Public License as published by 21 | * the Free Software Foundation; either version 2 of the License, or 22 | * (at your option) any later version. 23 | * 24 | * This program is distributed in the hope that it will be useful, 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | * GNU General Public License for more details. 28 | * 29 | * You should have received a copy of the GNU General Public License 30 | * along with this program; if not, write to the Free Software 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 32 | * 33 | * Should you need to contact me, the author, you can do so either by 34 | * e-mail - mail your message to , or by paper mail: 35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 36 | */ 37 | 38 | #ifndef SERIO_PENMOUNT 39 | #define SERIO_PENMOUNT 0x31 40 | #endif 41 | 42 | #ifndef SERIO_TOUCHRIGHT 43 | #define SERIO_TOUCHRIGHT 0x32 44 | #endif 45 | 46 | #ifndef SERIO_TOUCHWIN 47 | #define SERIO_TOUCHWIN 0x33 48 | #endif 49 | 50 | #ifndef SERIO_FUJITSU 51 | #define SERIO_FUJITSU 0x35 52 | #endif 53 | 54 | #ifndef SERIO_TOUCHIT213 55 | #define SERIO_TOUCHIT213 0x38 56 | #endif 57 | 58 | #ifndef SERIO_IRTOUCH 59 | #define SERIO_IRTOUCH 0x41 60 | #endif 61 | 62 | 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | 74 | static int readchar(int fd, unsigned char *c, int timeout) 75 | { 76 | struct timeval tv; 77 | fd_set set; 78 | 79 | tv.tv_sec = 0; 80 | tv.tv_usec = timeout * 1000; 81 | 82 | FD_ZERO(&set); 83 | FD_SET(fd, &set); 84 | 85 | if (!select(fd + 1, &set, NULL, NULL, &tv)) 86 | return -1; 87 | 88 | if (read(fd, c, 1) != 1) 89 | return -1; 90 | 91 | return 0; 92 | } 93 | 94 | static void setline(int fd, int flags, int speed) 95 | { 96 | struct termios t; 97 | 98 | tcgetattr(fd, &t); 99 | 100 | t.c_cflag = flags | CREAD | HUPCL | CLOCAL; 101 | t.c_iflag = IGNBRK | IGNPAR; 102 | t.c_oflag = 0; 103 | t.c_lflag = 0; 104 | t.c_cc[VMIN ] = 1; 105 | t.c_cc[VTIME] = 0; 106 | 107 | cfsetispeed(&t, speed); 108 | cfsetospeed(&t, speed); 109 | 110 | tcsetattr(fd, TCSANOW, &t); 111 | } 112 | 113 | static int logitech_command(int fd, char *c) 114 | { 115 | int i; 116 | unsigned char d; 117 | 118 | for (i = 0; c[i]; i++) { 119 | write(fd, c + i, 1); 120 | if (readchar(fd, &d, 1000)) 121 | return -1; 122 | if (c[i] != d) 123 | return -1; 124 | } 125 | return 0; 126 | } 127 | 128 | static int magellan_init(int fd, unsigned long *id, unsigned long *extra) 129 | { 130 | write(fd, "m3\rpBB\rz\r", 9); 131 | return 0; 132 | } 133 | 134 | static int warrior_init(int fd, unsigned long *id, unsigned long *extra) 135 | { 136 | if (logitech_command(fd, "*S")) 137 | return -1; 138 | 139 | setline(fd, CS8, B4800); 140 | return 0; 141 | } 142 | 143 | static int spaceball_waitchar(int fd, unsigned char c, char *d, 144 | int timeout) 145 | { 146 | unsigned char b = 0; 147 | 148 | while (!readchar(fd, &b, timeout)) { 149 | if (b == 0x0a) 150 | continue; 151 | *d++ = b; 152 | if (b == c) 153 | break; 154 | } 155 | 156 | *d = 0; 157 | 158 | return -(b != c); 159 | } 160 | 161 | static int spaceball_waitcmd(int fd, char c, char *d) 162 | { 163 | int i; 164 | 165 | for (i = 0; i < 8; i++) { 166 | if (spaceball_waitchar(fd, 0x0d, d, 1000)) 167 | return -1; 168 | if (d[0] == c) 169 | return 0; 170 | } 171 | 172 | return -1; 173 | } 174 | 175 | static int spaceball_cmd(int fd, char *c, char *d) 176 | { 177 | int i; 178 | 179 | for (i = 0; c[i]; i++) 180 | write(fd, c + i, 1); 181 | write(fd, "\r", 1); 182 | 183 | i = spaceball_waitcmd(fd, toupper(c[0]), d); 184 | 185 | return i; 186 | } 187 | 188 | #define SPACEBALL_1003 1 189 | #define SPACEBALL_2003B 3 190 | #define SPACEBALL_2003C 4 191 | #define SPACEBALL_3003C 7 192 | #define SPACEBALL_4000FLX 8 193 | #define SPACEBALL_4000FLX_L 9 194 | 195 | static int spaceball_init(int fd, unsigned long *id, unsigned long *extra) 196 | { 197 | char r[64]; 198 | 199 | if (spaceball_waitchar(fd, 0x11, r, 4000) || 200 | spaceball_waitchar(fd, 0x0d, r, 1000)) 201 | return -1; 202 | 203 | if (spaceball_waitcmd(fd, '@', r)) 204 | return -1; 205 | 206 | if (strncmp("@1 Spaceball alive", r, 18)) 207 | return -1; 208 | 209 | if (spaceball_waitcmd(fd, '@', r)) 210 | return -1; 211 | 212 | if (spaceball_cmd(fd, "hm", r)) 213 | return -1; 214 | 215 | if (!strncmp("Hm2003B", r, 7)) 216 | *id = SPACEBALL_2003B; 217 | if (!strncmp("Hm2003C", r, 7)) 218 | *id = SPACEBALL_2003C; 219 | if (!strncmp("Hm3003C", r, 7)) 220 | *id = SPACEBALL_3003C; 221 | 222 | if (!strncmp("HvFirmware", r, 10)) { 223 | 224 | if (spaceball_cmd(fd, "\"", r)) 225 | return -1; 226 | 227 | if (strncmp("\"1 Spaceball 4000 FLX", r, 21)) 228 | return -1; 229 | 230 | if (spaceball_waitcmd(fd, '"', r)) 231 | return -1; 232 | 233 | if (strstr(r, " L ")) 234 | *id = SPACEBALL_4000FLX_L; 235 | else 236 | *id = SPACEBALL_4000FLX; 237 | 238 | if (spaceball_waitcmd(fd, '"', r)) 239 | return -1; 240 | 241 | if (spaceball_cmd(fd, "YS", r)) 242 | return -1; 243 | 244 | if (spaceball_cmd(fd, "M", r)) 245 | return -1; 246 | 247 | return 0; 248 | } 249 | 250 | if (spaceball_cmd(fd, "P@A@A", r) || 251 | spaceball_cmd(fd, "FT@", r) || 252 | spaceball_cmd(fd, "MSS", r)) 253 | return -1; 254 | 255 | return 0; 256 | } 257 | 258 | static int stinger_init(int fd, unsigned long *id, unsigned long *extra) 259 | { 260 | int i; 261 | unsigned char c; 262 | unsigned char *response = (unsigned char *)"\r\n0600520058C272"; 263 | 264 | if (write(fd, " E5E5", 5) != 5) /* Enable command */ 265 | return -1; 266 | 267 | for (i = 0; i < 16; i++) /* Check for Stinger */ 268 | if (readchar(fd, &c, 200) || c != response[i]) 269 | return -1; 270 | 271 | return 0; 272 | } 273 | 274 | static int mzp_init(int fd, unsigned long *id, unsigned long *extra) 275 | { 276 | if (logitech_command(fd, "*X*q")) 277 | return -1; 278 | 279 | setline(fd, CS8, B9600); 280 | return 0; 281 | } 282 | 283 | static int newton_init(int fd, unsigned long *id, unsigned long *extra) 284 | { 285 | int i; 286 | unsigned char c; 287 | unsigned char response[35] = { 288 | 0x16, 0x10, 0x02, 0x64, 0x5f, 0x69, 0x64, 0x00, 289 | 0x00, 0x00, 0x0c, 0x6b, 0x79, 0x62, 0x64, 0x61, 290 | 0x70, 0x70, 0x6c, 0x00, 0x00, 0x00, 0x01, 0x6e, 291 | 0x6f, 0x66, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x10, 292 | 0x03, 0xdd, 0xe7 293 | }; 294 | 295 | for (i = 0; i < sizeof(response); i++) 296 | if (readchar(fd, &c, 400) || c != response[i]) 297 | return -1; 298 | 299 | return 0; 300 | } 301 | 302 | static int twiddler_init(int fd, unsigned long *id, unsigned long *extra) 303 | { 304 | unsigned char c[10]; 305 | int count, line; 306 | 307 | /* Turn DTR off, otherwise the Twiddler won't send any data. */ 308 | if (ioctl(fd, TIOCMGET, &line)) 309 | return -1; 310 | line &= ~TIOCM_DTR; 311 | if (ioctl(fd, TIOCMSET, &line)) 312 | return -1; 313 | 314 | /* 315 | * Check whether the device on the serial line is the Twiddler. 316 | * 317 | * The Twiddler sends data packets of 5 bytes which have the following 318 | * properties: the MSB is 0 on the first and 1 on all other bytes, and 319 | * the high order nibble of the last byte is always 0x8. 320 | * 321 | * We read and check two of those 5 byte packets to be sure that we 322 | * are indeed talking to a Twiddler. 323 | */ 324 | 325 | /* Read at most 5 bytes until we find one with the MSB set to 0 */ 326 | for (count = 0; count < 5; count++) { 327 | if (readchar(fd, c, 500)) 328 | return -1; 329 | if ((c[0] & 0x80) == 0) 330 | break; 331 | } 332 | 333 | if (count == 5) { 334 | /* Could not find header byte in data stream */ 335 | return -1; 336 | } 337 | 338 | /* Read remaining 4 bytes plus the full next data packet */ 339 | for (count = 1; count < 10; count++) 340 | if (readchar(fd, c + count, 500)) 341 | return -1; 342 | 343 | /* Check whether the bytes of both data packets obey the rules */ 344 | for (count = 1; count < 10; count++) { 345 | if ((count % 5 == 0 && (c[count] & 0x80) != 0x00) || 346 | (count % 5 == 4 && (c[count] & 0xF0) != 0x80) || 347 | (count % 5 != 0 && (c[count] & 0x80) != 0x80)) { 348 | /* Invalid byte in data packet */ 349 | return -1; 350 | } 351 | } 352 | 353 | return 0; 354 | } 355 | 356 | static int fujitsu_init(int fd, unsigned long *id, unsigned long *extra) 357 | { 358 | unsigned char cmd, data; 359 | 360 | /* Wake up the touchscreen */ 361 | cmd = 0xff; /* Dummy data */; 362 | if (write(fd, &cmd, 1) != 1) 363 | return -1; 364 | 365 | /* Wait to settle down */ 366 | usleep(100 * 1000); /* 100 ms */ 367 | 368 | /* Reset the touchscreen */ 369 | cmd = 0x81; /* Cold reset */ 370 | if (write(fd, &cmd, 1) != 1) 371 | return -1; 372 | 373 | /* Read ACK */ 374 | if (readchar(fd, &data, 100) || (data & 0xbf) != 0x90) 375 | return -1; 376 | 377 | /* Read status */ 378 | if (readchar(fd, &data, 100) || data != 0x00) 379 | return -1; 380 | 381 | return 0; 382 | } 383 | 384 | static int t213_init(int fd, unsigned long *id, unsigned long *extra) 385 | { 386 | char cmd[]={0x0a,1,'A'}; 387 | int count=10; 388 | int state=0; 389 | unsigned char data; 390 | 391 | /* 392 | * In case the controller is in "ELO-mode" send a few times 393 | * the check active packet to force it into the documented 394 | * touchkit mode. 395 | */ 396 | while (count>0) { 397 | if (write(fd, &cmd, 3) != 3) 398 | return -1; 399 | while (!readchar(fd, &data, 100)) { 400 | switch (state) { 401 | case 0: 402 | if (data==0x0a) { 403 | state=1; 404 | } 405 | break; 406 | case 1: 407 | if (data==1) { 408 | state=2; 409 | } else if (data!=0x0a) { 410 | state=0; 411 | } 412 | break; 413 | case 2: 414 | if (data=='A') { 415 | return 0; 416 | } else if (data==0x0a) { 417 | state=1; 418 | } else { 419 | state=0; 420 | } 421 | break; 422 | } 423 | 424 | } 425 | count--; 426 | } 427 | return -1; 428 | } 429 | 430 | static int dump_init(int fd, unsigned long *id, unsigned long *extra) 431 | { 432 | unsigned char c, o = 0; 433 | 434 | c = 0x80; 435 | 436 | if (write(fd, &c, 1) != 1) /* Enable command */ 437 | return -1; 438 | 439 | while (1) 440 | if (!readchar(fd, &c, 1)) { 441 | printf("%02x (%c) ", c, ((c > 32) && (c < 127)) ? c : 'x'); 442 | o = 1; 443 | } else { 444 | if (o) { 445 | printf("\n"); 446 | o = 0; 447 | } 448 | } 449 | } 450 | 451 | struct input_types { 452 | const char *name; 453 | const char *name2; 454 | const char *desc; 455 | int speed; 456 | int flags; 457 | unsigned long type; 458 | unsigned long id; 459 | unsigned long extra; 460 | int flush; 461 | int (*init)(int fd, unsigned long *id, unsigned long *extra); 462 | }; 463 | 464 | static struct input_types input_types[] = { 465 | { "--sunkbd", "-skb", "Sun Type 4 and Type 5 keyboards", 466 | B1200, CS8, 467 | SERIO_SUNKBD, 0x00, 0x00, 1, NULL }, 468 | { "--lkkbd", "-lk", "DEC LK201 / LK401 keyboards", 469 | B4800, CS8|CSTOPB, 470 | SERIO_LKKBD, 0x00, 0x00, 1, NULL }, 471 | { "--vsxxx-aa", "-vs", 472 | "DEC VSXXX-AA / VSXXX-GA mouse and VSXXX-A tablet", 473 | B4800, CS8|CSTOPB|PARENB|PARODD, 474 | SERIO_VSXXXAA, 0x00, 0x00, 1, NULL }, 475 | { "--spaceorb", "-orb", "SpaceOrb 360 / SpaceBall Avenger", 476 | B9600, CS8, 477 | SERIO_SPACEORB, 0x00, 0x00, 1, NULL }, 478 | { "--spaceball", "-sbl", "SpaceBall 2003 / 3003 / 4000 FLX", 479 | B9600, CS8, 480 | SERIO_SPACEBALL, 0x00, 0x00, 0, spaceball_init }, 481 | { "--magellan", "-mag", "Magellan / SpaceMouse", 482 | B9600, CS8 | CSTOPB | CRTSCTS, 483 | SERIO_MAGELLAN, 0x00, 0x00, 1, magellan_init }, 484 | { "--warrior", "-war", "WingMan Warrior", 485 | B1200, CS7 | CSTOPB, 486 | SERIO_WARRIOR, 0x00, 0x00, 1, warrior_init }, 487 | { "--stinger", "-sting", "Gravis Stinger", 488 | B1200, CS8, 489 | SERIO_STINGER, 0x00, 0x00, 1, stinger_init }, 490 | { "--mousesystems", "-msc", "3-button Mouse Systems mouse", 491 | B1200, CS8, 492 | SERIO_MSC, 0x00, 0x01, 1, NULL }, 493 | { "--sunmouse", "-sun", "3-button Sun mouse", 494 | B1200, CS8, 495 | SERIO_SUN, 0x00, 0x01, 1, NULL }, 496 | { "--microsoft", "-bare", "2-button Microsoft mouse", 497 | B1200, CS7, 498 | SERIO_MS, 0x00, 0x00, 1, NULL }, 499 | { "--mshack", "-ms", "3-button mouse in Microsoft mode", 500 | B1200, CS7, 501 | SERIO_MS, 0x00, 0x01, 1, NULL }, 502 | { "--mouseman", "-mman", "3-button Logitech / Genius mouse", 503 | B1200, CS7, 504 | SERIO_MP, 0x00, 0x01, 1, NULL }, 505 | { "--intellimouse", "-ms3", "Microsoft IntelliMouse", 506 | B1200, CS7, 507 | SERIO_MZ, 0x00, 0x11, 1, NULL }, 508 | { "--mmwheel", "-mmw", 509 | "Logitech mouse with 4-5 buttons or a wheel", 510 | B1200, CS7 | CSTOPB, 511 | SERIO_MZP, 0x00, 0x13, 1, mzp_init }, 512 | { "--iforce", "-ifor", "I-Force joystick or wheel", 513 | B38400, CS8, 514 | SERIO_IFORCE, 0x00, 0x00, 0, NULL }, 515 | { "--newtonkbd", "-newt", "Newton keyboard", 516 | B9600, CS8, 517 | SERIO_NEWTON, 0x00, 0x00, 1, newton_init }, 518 | { "--h3600ts", "-ipaq", "Ipaq h3600 touchscreen", 519 | B115200, CS8, 520 | SERIO_H3600, 0x00, 0x00, 0, NULL }, 521 | { "--stowawaykbd", "-ipaqkbd", "Stowaway keyboard", 522 | B115200, CS8, 523 | SERIO_STOWAWAY, 0x00, 0x00, 1, NULL }, 524 | { "--ps2serkbd", "-ps2ser", "PS/2 via serial keyboard", 525 | B1200, CS8, 526 | SERIO_PS2SER, 0x00, 0x00, 1, NULL }, 527 | { "--twiddler", "-twid", "Handykey Twiddler chording keyboard", 528 | B2400, CS8, 529 | SERIO_TWIDKBD, 0x00, 0x00, 0, twiddler_init }, 530 | { "--twiddler-joy", "-twidjoy", "Handykey Twiddler used as a joystick", 531 | B2400, CS8, 532 | SERIO_TWIDJOY, 0x00, 0x00, 0, twiddler_init }, 533 | { "--elotouch", "-elo", "ELO touchscreen, 10-byte mode", 534 | B9600, CS8 | CRTSCTS, 535 | SERIO_ELO, 0x00, 0x00, 0, NULL }, 536 | { "--elo4002", "-elo6b", "ELO touchscreen, 6-byte mode", 537 | B9600, CS8 | CRTSCTS, 538 | SERIO_ELO, 0x01, 0x00, 0, NULL }, 539 | { "--elo271-140", "-elo4b", "ELO touchscreen, 4-byte mode", 540 | B9600, CS8 | CRTSCTS, 541 | SERIO_ELO, 0x02, 0x00, 0, NULL }, 542 | { "--elo261-280", "-elo3b", "ELO Touchscreen, 3-byte mode", 543 | B9600, CS8 | CRTSCTS, 544 | SERIO_ELO, 0x03, 0x00, 0, NULL }, 545 | { "--mtouch", "-mtouch", "MicroTouch (3M) touchscreen", 546 | B9600, CS8 | CRTSCTS, 547 | SERIO_MICROTOUCH, 0x00, 0x00, 0, NULL }, 548 | { "--touchit213", "-t213", "Sahara Touch-iT213 Tablet PC", 549 | B9600, CS8, 550 | SERIO_TOUCHIT213, 0x00, 0x00, 0, t213_init }, 551 | { "--touchright", "-tr", "Touchright serial touchscreen", 552 | B9600, CS8 | CRTSCTS, 553 | SERIO_TOUCHRIGHT, 0x00, 0x00, 0, NULL }, 554 | { "--touchwin", "-tw", "Touchwindow serial touchscreen", 555 | B4800, CS8 | CRTSCTS, 556 | SERIO_TOUCHWIN, 0x00, 0x00, 0, NULL }, 557 | { "--penmount", "-pm", "Penmount touchscreen", 558 | B19200, CS8 | CRTSCTS, 559 | SERIO_PENMOUNT, 0x00, 0x00, 0, NULL }, 560 | { "--fujitsu", "-fjt", "Fujitsu serial touchscreen", 561 | B9600, CS8, 562 | SERIO_FUJITSU, 0x00, 0x00, 1, NULL }, 563 | { "--irtouch", "-irts", "IR Touch touchscreen", 564 | B38400, CS8, 565 | SERIO_IRTOUCH, 0x00, 0x00, 0, NULL }, 566 | { "--dump", "-dump", "Just enable device", 567 | B2400, CS8, 568 | 0, 0x00, 0x00, 0, dump_init }, 569 | { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, NULL } 570 | }; 571 | 572 | static void show_help(void) 573 | { 574 | struct input_types *type; 575 | 576 | puts(""); 577 | puts("Usage: inputattach [--daemon] [--always] [--noinit] "); 578 | puts(""); 579 | puts("Modes:"); 580 | 581 | for (type = input_types; type->name; type++) 582 | printf(" %-16s %-8s %s\n", 583 | type->name, type->name2, type->desc); 584 | 585 | puts(""); 586 | } 587 | 588 | int main(int argc, char **argv) 589 | { 590 | unsigned long devt; 591 | int ldisc; 592 | struct input_types *type = NULL; 593 | const char *device = NULL; 594 | int daemon_mode = 0; 595 | int need_device = 0; 596 | unsigned long id, extra; 597 | int fd; 598 | int i; 599 | unsigned char c; 600 | int retval; 601 | int ignore_init_res = 0; 602 | int no_init = 0; 603 | 604 | for (i = 1; i < argc; i++) { 605 | if (!strcasecmp(argv[i], "--help")) { 606 | show_help(); 607 | return EXIT_SUCCESS; 608 | } else if (!strcasecmp(argv[i], "--daemon")) { 609 | daemon_mode = 1; 610 | } else if (!strcasecmp(argv[i], "--always")) { 611 | ignore_init_res = 1; 612 | } else if (!strcasecmp(argv[i], "--noinit")) { 613 | no_init = 1; 614 | } else if (need_device) { 615 | device = argv[i]; 616 | need_device = 0; 617 | } else { 618 | if (type && type->name) { 619 | fprintf(stderr, 620 | "inputattach: '%s' - " 621 | "only one mode allowed\n", argv[i]); 622 | return EXIT_FAILURE; 623 | } 624 | for (type = input_types; type->name; type++) { 625 | if (!strcasecmp(argv[i], type->name) || 626 | !strcasecmp(argv[i], type->name2)) { 627 | break; 628 | } 629 | } 630 | if (!type->name) { 631 | fprintf(stderr, 632 | "inputattach: invalid mode '%s'\n", 633 | argv[i]); 634 | return EXIT_FAILURE; 635 | } 636 | need_device = 1; 637 | } 638 | } 639 | 640 | if (!type || !type->name) { 641 | fprintf(stderr, "inputattach: must specify mode\n"); 642 | return EXIT_FAILURE; 643 | } 644 | 645 | if (need_device) { 646 | fprintf(stderr, "inputattach: must specify device\n"); 647 | return EXIT_FAILURE; 648 | } 649 | 650 | fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); 651 | if (fd < 0) { 652 | fprintf(stderr, "inputattach: '%s' - %s\n", 653 | device, strerror(errno)); 654 | return 1; 655 | } 656 | 657 | setline(fd, type->flags, type->speed); 658 | 659 | if (type->flush) 660 | while (!readchar(fd, &c, 100)) 661 | /* empty */; 662 | 663 | id = type->id; 664 | extra = type->extra; 665 | 666 | if (type->init && !no_init) { 667 | if (type->init(fd, &id, &extra)) { 668 | if (ignore_init_res) { 669 | fprintf(stderr, "inputattach: ignored device initialization failure\n"); 670 | } else { 671 | fprintf(stderr, "inputattach: device initialization failed\n"); 672 | return EXIT_FAILURE; 673 | } 674 | } 675 | } 676 | 677 | ldisc = N_MOUSE; 678 | if (ioctl(fd, TIOCSETD, &ldisc)) { 679 | fprintf(stderr, "inputattach: can't set line discipline\n"); 680 | return EXIT_FAILURE; 681 | } 682 | 683 | devt = type->type | (id << 8) | (extra << 16); 684 | 685 | if (ioctl(fd, SPIOCSTYPE, &devt)) { 686 | fprintf(stderr, "inputattach: can't set device type\n"); 687 | return EXIT_FAILURE; 688 | } 689 | 690 | retval = EXIT_SUCCESS; 691 | if (daemon_mode && daemon(0, 0) < 0) { 692 | perror("inputattach"); 693 | retval = EXIT_FAILURE; 694 | } 695 | 696 | read(fd, NULL, 0); 697 | 698 | ldisc = 0; 699 | ioctl(fd, TIOCSETD, &ldisc); 700 | close(fd); 701 | 702 | return retval; 703 | } 704 | -------------------------------------------------------------------------------- /ipu_bufs.cpp: -------------------------------------------------------------------------------- 1 | #include "physMem.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include /* getopt_long() */ 8 | 9 | #include /* low-level i/o */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include /* for videodev2.h */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #if defined (MX51) 29 | #define IPU_CPMEM_REG_BASE 0X5F000000 30 | #define IPU_CM_REG_BASE 0x5E000000 31 | #elif defined (MX53) 32 | #define IPU_CPMEM_REG_BASE 0x1F000000 33 | #define IPU_CM_REG_BASE 0x1E000000 34 | #else 35 | #error need to define MX51 or MX53 36 | #endif 37 | 38 | #define PAGE_SIZE 4096 39 | 40 | struct ipu_ch_param_word { 41 | unsigned data[5]; 42 | unsigned res[3]; 43 | }; 44 | 45 | struct ipu_ch_param { 46 | struct ipu_ch_param_word word[2]; 47 | }; 48 | 49 | #define ARRAYSIZE(__arr) (sizeof(__arr)/sizeof(__arr[0])) 50 | 51 | 52 | static unsigned const buf_offsets[] = { 53 | 0x268 54 | , 0x270 55 | }; 56 | 57 | static void print_field( 58 | char const *name, 59 | struct ipu_ch_param_word const ¶m_word, 60 | unsigned startbit, 61 | unsigned numbits) 62 | { 63 | unsigned value ; 64 | unsigned wordnum=(startbit/32); 65 | if( wordnum == ((startbit+numbits-1)/32) ) { 66 | unsigned shifted = (param_word.data[wordnum] >> (startbit & 31)); 67 | value = shifted & ((1<> (startbit & 31)) & ((1< max ){ 93 | fprintf(stderr, "Error: range of %s is [0..0x%x]\n", field.name, max ); 94 | return ; 95 | } 96 | unsigned wordnum=(field.startbit/32); 97 | if( wordnum == ((field.startbit+field.numbits-1)/32) ) { 98 | unsigned shifted = value << (field.startbit & 31); 99 | unsigned mask = ~(max << (field.startbit&31)); 100 | unsigned oldval = param_word.data[wordnum] & ~mask ; 101 | printf( "single word value 0x%08x, mask 0x%08x, oldval 0x%08x\n", shifted, mask, oldval ); 102 | if( shifted != oldval ) { 103 | param_word.data[wordnum] = (param_word.data[wordnum]&mask) | shifted ; 104 | printf( "value changed\n"); 105 | } 106 | } /* fits in one word */ 107 | else { 108 | printf( "no multi-word support yet\n" ); 109 | unsigned oldlow = param_word.data[wordnum]; 110 | unsigned lowbits = 32-(field.startbit&31); 111 | unsigned lowval = value & ((1<> lowbits ; 117 | unsigned newhigh = (oldhigh&(~((1< argc ){ 165 | fprintf(stderr, "Usage: %s buffernum [field value]\n", argv[0]); 166 | return -1 ; 167 | } 168 | physMem_t cpmem(IPU_CPMEM_REG_BASE, PAGE_SIZE,O_RDWR); 169 | if( !cpmem.worked() ){ 170 | perror("cpmem"); 171 | return -1 ; 172 | } 173 | 174 | physMem_t cmmem(IPU_CM_REG_BASE, PAGE_SIZE); 175 | if( !cmmem.worked() ){ 176 | perror("cmmem"); 177 | return -1 ; 178 | } 179 | unsigned char const *rdy_base = (unsigned char *)cmmem.ptr(); 180 | 181 | unsigned const *cur_buf_base = (unsigned *)(rdy_base + 0x23C); 182 | 183 | ipu_ch_param *params = (ipu_ch_param *)cpmem.ptr(); 184 | unsigned chan = strtoul(argv[1],0,0); 185 | if( 80 >= chan ){ 186 | printf( "--------------- ipu ch %u ---------------\n", chan ); 187 | ipu_ch_param ¶m = params[chan]; 188 | for( unsigned i = 0 ; i < ARRAYSIZE(param.word); i++ ){ 189 | struct ipu_ch_param_word const &w = param.word[i]; 190 | unsigned addr = (char *)&w - (char *)params + IPU_CPMEM_REG_BASE ; 191 | printf( "[%08x]: ", addr ); 192 | for(unsigned j = 0 ; j < ARRAYSIZE(w.data); j++ ) { 193 | unsigned char *bytes = (unsigned char *)(w.data+j); 194 | for( unsigned char b = 0 ; b < 4 ; b++ ){ 195 | printf( "%02x ", bytes[b]); 196 | } 197 | printf( " " ); 198 | } 199 | printf("\n"); 200 | } 201 | // printf( "bufs == %08x %08x\n", param.word[1].data[0], param.word[1].data[1]); 202 | unsigned long addrs[] = { 203 | (param.word[1].data[0] & ((1<<29)-1))*8, 204 | ((param.word[1].data[0] >> 29)|(param.word[1].data[1]<<3))*8 205 | }; 206 | 207 | unsigned curbuf_long = chan/32 ; 208 | unsigned curbuf_bit = chan%31 ; 209 | unsigned curbuf = (cur_buf_base[curbuf_long] >> curbuf_bit)&1 ; 210 | 211 | for( unsigned i = 0 ; i < 2 ; i++ ){ 212 | unsigned char bits = rdy_base[buf_offsets[i]+chan/8]; 213 | unsigned char mask = 1<<(chan&7); 214 | bool ready = 0 != (bits & mask); 215 | printf( "ipu_buf[chan %u][%d] == 0x%08lx %s %s\n", chan, i, addrs[i], 216 | ready ? "READY" : "NOT READY", 217 | (i==curbuf) ? "<-- current" : ""); 218 | } 219 | 220 | if( 2 < argc ) { 221 | char const *fieldname = argv[2]; 222 | for( unsigned i = 0 ; i < ARRAYSIZE(fields); i++ ){ 223 | if( 0 == strcmp(fields[i].name,fieldname)) { 224 | print_field(fields[i].name, 225 | param.word[fields[i].wordnum], 226 | fields[i].startbit, 227 | fields[i].numbits); 228 | if( 3 < argc ) { 229 | unsigned const value = strtoul(argv[3],0,0); 230 | set_field(param.word[fields[i].wordnum],fields[i],value); 231 | } 232 | return 0 ; 233 | } 234 | } 235 | fprintf( stderr, "field %s not found\n", fieldname ); 236 | } else { 237 | for( unsigned i = 0 ; i < ARRAYSIZE(fields); i++ ){ 238 | print_field(fields[i].name,param.word[fields[i].wordnum],fields[i].startbit,fields[i].numbits); 239 | } 240 | } // print all fields 241 | } else 242 | fprintf(stderr, "Invalid channel %s, 0x%x\n", argv[1],chan); 243 | 244 | return 0 ; 245 | } 246 | -------------------------------------------------------------------------------- /libjpeg_encoder.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * libjpeg_encoder.cpp: define an encoder class to produce JPEG encoded 3 | * output from a YUV image. 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "hexDump.h" 12 | #include "fourcc.h" 13 | 14 | extern "C" { 15 | #include 16 | }; 17 | 18 | #define BYTESPERMEMCHUNK 16384 19 | 20 | struct memChunk_t { 21 | unsigned long length_ ; // bytes used so far 22 | memChunk_t *next_ ; // next chunk 23 | JOCTET data_[BYTESPERMEMCHUNK-8]; 24 | }; 25 | 26 | struct memDest_t { 27 | struct jpeg_destination_mgr pub; /* public fields */ 28 | memChunk_t *chunkHead_ ; 29 | memChunk_t *chunkTail_ ; 30 | }; 31 | 32 | typedef memDest_t *memDestPtr_t ; 33 | 34 | static void dumpcinfo( jpeg_compress_struct const &cinfo ) 35 | { 36 | hexDumper_t dump( &cinfo, sizeof( cinfo ) ); 37 | while( dump.nextLine() ) 38 | printf( "%s\n", dump.getLine() ); 39 | fflush( stdout ); 40 | } 41 | 42 | static void dumpMemDest( memDest_t const &md ) 43 | { 44 | hexDumper_t dump( &md, sizeof( md ) ); 45 | while( dump.nextLine() ) 46 | printf( "%s\n", dump.getLine() ); 47 | fflush( stdout ); 48 | } 49 | 50 | /* 51 | * Initialize destination --- called by jpeg_start_compress 52 | * before any data is actually written. 53 | */ 54 | static void init_destination (j_compress_ptr cinfo) 55 | { 56 | memDestPtr_t dest = (memDestPtr_t) cinfo->dest; 57 | 58 | assert( 0 == dest->chunkHead_ ); 59 | 60 | /* Allocate first memChunk */ 61 | dest->chunkHead_ = dest->chunkTail_ = new memChunk_t ; 62 | memset( dest->chunkHead_, 0, sizeof( *dest->chunkHead_ ) ); 63 | dest->pub.next_output_byte = dest->chunkHead_->data_ ; 64 | dest->pub.free_in_buffer = sizeof( dest->chunkHead_->data_ ); 65 | } 66 | 67 | 68 | /* 69 | * Empty the output buffer --- called whenever buffer fills up. 70 | */ 71 | 72 | static boolean empty_output_buffer (j_compress_ptr cinfo) 73 | { 74 | memDestPtr_t const dest = (memDestPtr_t) cinfo->dest; 75 | 76 | assert( 0 != dest->chunkTail_ ); 77 | 78 | // 79 | // free_in_buffer member doesn't seem to be filled in 80 | // 81 | dest->chunkTail_->length_ = sizeof( dest->chunkTail_->data_ ); // - dest->pub.free_in_buffer ; 82 | 83 | memChunk_t * const next = new memChunk_t ; 84 | memset( next, 0, sizeof( *next ) ); 85 | dest->chunkTail_->next_ = next ; 86 | dest->chunkTail_ = next ; 87 | 88 | dest->pub.next_output_byte = next->data_ ; 89 | dest->pub.free_in_buffer = sizeof( next->data_ ); 90 | 91 | return TRUE; 92 | } 93 | 94 | 95 | /* 96 | * Terminate destination --- called by jpeg_finish_compress 97 | * after all data has been written. Usually needs to flush buffer. 98 | * 99 | * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding 100 | * application must deal with any cleanup that should happen even 101 | * for error exit. 102 | */ 103 | static void term_destination (j_compress_ptr cinfo) 104 | { 105 | // 106 | // just account for data used 107 | // 108 | memDest_t *const dest = (memDestPtr_t) cinfo->dest ; 109 | memChunk_t *tail = dest->chunkTail_ ; 110 | assert( 0 != tail ); 111 | assert( sizeof( tail->data_ ) >= dest->pub.free_in_buffer ); 112 | assert( tail->data_ <= dest->pub.next_output_byte ); 113 | assert( tail->data_ + sizeof( tail->data_ ) >= dest->pub.next_output_byte + dest->pub.free_in_buffer ); 114 | 115 | tail->length_ = sizeof( tail->data_ ) - dest->pub.free_in_buffer ; 116 | } 117 | 118 | /* 119 | * Prepare for output to a chunked memory stream. 120 | */ 121 | void jpeg_mem_dest( j_compress_ptr cinfo ) 122 | { 123 | assert( 0 == cinfo->dest ); 124 | cinfo->dest = (struct jpeg_destination_mgr *) 125 | (*cinfo->mem->alloc_small) 126 | ( (j_common_ptr) cinfo, 127 | JPOOL_IMAGE, 128 | sizeof(memDest_t) 129 | ); 130 | memDest_t *dest = (memDest_t *) cinfo->dest ; 131 | dest->pub.init_destination = init_destination ; 132 | dest->pub.empty_output_buffer = empty_output_buffer ; 133 | dest->pub.term_destination = term_destination ; 134 | dest->chunkHead_ = 135 | dest->chunkTail_ = 0 ; 136 | } 137 | 138 | struct resolution_t { 139 | unsigned w ; 140 | unsigned h ; 141 | }; 142 | 143 | static struct resolution_t const known_resolutions[] = { 144 | { 640, 480 } 145 | }; 146 | 147 | #define ARRAY_SIZE(__arr) (sizeof(__arr)/sizeof(__arr[0])) 148 | 149 | static resolution_t const *find_res(unsigned ybytes){ 150 | for (int i = 0 ; i < ARRAY_SIZE(known_resolutions); i++) { 151 | if (ybytes == (known_resolutions[i].w*known_resolutions[i].h)) { 152 | return known_resolutions+i; 153 | } 154 | } 155 | return 0 ; 156 | } 157 | 158 | #include "libjpeg_encoder.h" 159 | 160 | libjpeg_encoder_t::libjpeg_encoder_t 161 | ( unsigned width, 162 | unsigned height, 163 | unsigned fourcc, 164 | unsigned char const *data, 165 | unsigned dataSize) 166 | : jpegData_(0) 167 | , jpegSize_(0) 168 | { 169 | if (!supported_fourcc(fourcc)) { 170 | fprintf (stderr, "Unsupported fourcc %s\n", fourcc_str(fourcc)); 171 | return ; 172 | } 173 | unsigned ysize; 174 | unsigned yoffs; 175 | unsigned yadder; 176 | unsigned uvsize; 177 | unsigned uvrowdiv; 178 | unsigned uvcoldiv; 179 | unsigned uoffs; 180 | unsigned voffs; 181 | unsigned uvadder; 182 | unsigned totalsize; 183 | if (!fourccOffsets(fourcc, 184 | width, 185 | height, 186 | ysize, 187 | yoffs, 188 | yadder, 189 | uvsize, 190 | uvrowdiv, 191 | uvcoldiv, 192 | uoffs, 193 | voffs, 194 | uvadder, 195 | totalsize)) { 196 | fprintf (stderr, "Error calculating params for fourcc %s\n", fourcc_str(fourcc)); 197 | return ; 198 | } 199 | if (totalsize != dataSize) { 200 | fprintf (stderr, "data size mismatch: %u != %u\n\n", totalsize, dataSize); 201 | return ; 202 | } 203 | struct jpeg_compress_struct cinfo; 204 | struct jpeg_error_mgr jerr; 205 | cinfo.err = jpeg_std_error(&jerr); 206 | jpeg_create_compress( &cinfo ); 207 | cinfo.in_color_space = JCS_YCbCr; /* arbitrary guess */ 208 | jpeg_set_defaults(&cinfo); 209 | cinfo.dct_method = JDCT_ISLOW; 210 | cinfo.in_color_space = JCS_YCbCr; 211 | cinfo.input_components = 3; 212 | cinfo.data_precision = 8; 213 | cinfo.image_width = (JDIMENSION)width; 214 | cinfo.image_height = (JDIMENSION)height; 215 | jpeg_set_colorspace(&cinfo,JCS_YCbCr); 216 | jpeg_set_quality(&cinfo,100,0); 217 | jpeg_mem_dest( &cinfo ); 218 | jpeg_start_compress( &cinfo, TRUE ); 219 | unsigned const row_stride = 3*sizeof(JSAMPLE)*width; // RGB 220 | JSAMPARRAY const buffer = (*cinfo.mem->alloc_sarray)( (j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1); 221 | unsigned char const *yIn = data+yoffs; 222 | unsigned char const *uIn = yIn+uoffs ; 223 | unsigned char const *vIn = yIn+voffs ; 224 | unsigned const uvstride = width/uvcoldiv; 225 | for( int row = 0 ; row < height ; row++ ) 226 | { 227 | JSAMPLE *nextOut = buffer[0]; 228 | unsigned rowoffs = (row/uvrowdiv)*uvstride; 229 | for( int col = 0 ; col < width ; col++ ) 230 | { 231 | unsigned coloffs = col/uvcoldiv; 232 | unsigned char u = (uIn+rowoffs)[coloffs]; 233 | unsigned char v = (vIn+rowoffs)[coloffs]; 234 | *nextOut++ = *yIn++ ; 235 | *nextOut++ = u ; 236 | *nextOut++ = v ; 237 | } // for each column 238 | jpeg_write_scanlines( &cinfo, buffer, 1 ); 239 | } // for each row 240 | jpeg_finish_compress( &cinfo ); 241 | 242 | memDest_t * const dest = (memDest_t *)cinfo.dest ; 243 | memChunk_t *chunk = dest->chunkHead_ ; 244 | unsigned numChunks = 0 ; 245 | totalsize=0; 246 | while (chunk) { 247 | ++numChunks ; 248 | totalsize += chunk->length_; 249 | chunk = chunk->next_ ; 250 | } 251 | 252 | jpegSize_ = totalsize ; 253 | unsigned char *nextOut = jpegData_ = new unsigned char [totalsize]; 254 | totalsize=0; 255 | 256 | while (dest->chunkHead_) { 257 | chunk = dest->chunkHead_->next_ ; 258 | memcpy(nextOut,dest->chunkHead_->data_,dest->chunkHead_->length_); 259 | nextOut += dest->chunkHead_->length_; 260 | delete dest->chunkHead_ ; 261 | dest->chunkHead_ = chunk ; 262 | } 263 | jpeg_destroy_compress(&cinfo); 264 | } 265 | 266 | libjpeg_encoder_t::~libjpeg_encoder_t( void ) 267 | { 268 | if (jpegData_) { 269 | delete [] jpegData_ ; 270 | } 271 | } 272 | 273 | 274 | #ifdef __MODULETEST_LIBJPEG_ENCODER__ 275 | #include "memFile.h" 276 | #include 277 | 278 | int main (int argc, char const * const argv[]) 279 | { 280 | if (4 > argc) { 281 | printf( "Usage: %s infile w h\n", argv[0]); 282 | return -1 ; 283 | } 284 | memFile_t fIn(argv[1]); 285 | if (!fIn.worked()) { 286 | perror(argv[1]); 287 | return -1; 288 | } 289 | unsigned w = strtoul(argv[2],0,0); 290 | unsigned h = strtoul(argv[3],0,0); 291 | unsigned iterations = 0 ; 292 | while (1) { 293 | libjpeg_encoder_t encoder(w,h,0x32315559, 294 | (unsigned char *)fIn.getData(), 295 | fIn.getLength()); 296 | if (encoder.worked()) { 297 | if ((4 < argc) && (0 == iterations)) { 298 | FILE *fOut = fopen(argv[4],"wb"); 299 | if (fOut) { 300 | fwrite(encoder.jpegData(),encoder.dataSize(),1,fOut); 301 | fclose(fOut); 302 | printf( "wrote %u bytes to %s\n", encoder.dataSize(),argv[4]); 303 | } else 304 | perror(argv[4]); 305 | } else 306 | printf( "%u bytes\n", encoder.dataSize()); 307 | } else { 308 | fprintf(stderr, "Error converting %s\n", argv[1]); 309 | break; 310 | } 311 | iterations++ ; 312 | } 313 | return 0 ; 314 | } 315 | #endif 316 | -------------------------------------------------------------------------------- /libjpeg_encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIBJPEG_ENCODER_H__ 2 | #define __LIBJPEG_ENCODER_H__ 3 | /* 4 | * libjpeg_encoder.h: 5 | * 6 | * Declares class libjpeg_encoder_t for use in producing JPEG-encoded 7 | * blob from a YUV image. 8 | * 9 | */ 10 | 11 | class libjpeg_encoder_t { 12 | public: 13 | libjpeg_encoder_t( unsigned width, 14 | unsigned height, 15 | unsigned fourcc, 16 | unsigned char const *data, 17 | unsigned dataSize); 18 | ~libjpeg_encoder_t( void ); 19 | bool worked( void ) const { return (0 != jpegData_); } 20 | unsigned char const *jpegData(void) const { return jpegData_; } 21 | unsigned dataSize(void) const { return jpegSize_ ; } 22 | private: 23 | unsigned char *jpegData_ ; 24 | unsigned jpegSize_ ; 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /makeVersion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | header_ver=`cat version.h 2>/dev/null |grep -w PLAYER_VERSION | sed 's/.* "//' | sed 's/"//'` ; 3 | repo_ver=`git rev-parse --verify HEAD` ; 4 | dirty_files=`git diff-index --name-only HEAD` ; 5 | if ! [ -z "$dirty_files" ]; then repo_ver="${repo_ver}-dirty" ; fi 6 | if [ "$header_ver" != "$repo_ver" ] ; then 7 | cat > version.h <= 32 bytes left */ 110 | add r2, r2, #64 111 | subs r2, r2, #32 112 | blo 4f 113 | 114 | 3: /* 32 bytes at a time. These cache lines were already preloaded */ 115 | vld1.8 {d0 - d3}, [r1]! 116 | subs r2, r2, #32 117 | vst1.8 {d0 - d3}, [r0, :128]! 118 | bhs 3b 119 | 120 | 4: /* less than 32 left */ 121 | add r2, r2, #32 122 | tst r2, #0x10 123 | beq 5f 124 | // copies 16 bytes, 128-bits aligned 125 | vld1.8 {d0, d1}, [r1]! 126 | vst1.8 {d0, d1}, [r0, :128]! 127 | 128 | 5: /* copy up to 15-bytes (count in r2) */ 129 | movs ip, r2, lsl #29 130 | bcc 1f 131 | vld1.8 {d0}, [r1]! 132 | vst1.8 {d0}, [r0]! 133 | 1: bge 2f 134 | vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! 135 | vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]! 136 | 2: movs ip, r2, lsl #31 137 | ldrmib r3, [r1], #1 138 | ldrcsb ip, [r1], #1 139 | ldrcsb lr, [r1], #1 140 | strmib r3, [r0], #1 141 | strcsb ip, [r0], #1 142 | strcsb lr, [r0], #1 143 | 144 | ldmfd sp!, {r0, lr} 145 | bx lr 146 | .fnend 147 | 148 | 149 | #else /* __ARM_ARCH__ < 7 */ 150 | 151 | .text 152 | 153 | .global memcopy 154 | .type memcopy, %function 155 | .align 4 156 | 157 | /* 158 | * Optimized memcopy() for ARM. 159 | * 160 | * note that memcopy() always returns the destination pointer, 161 | * so we have to preserve R0. 162 | */ 163 | 164 | memcopy: 165 | /* The stack must always be 64-bits aligned to be compliant with the 166 | * ARM ABI. Since we have to save R0, we might as well save R4 167 | * which we can use for better pipelining of the reads below 168 | */ 169 | .fnstart 170 | .save {r0, r4, lr} 171 | stmfd sp!, {r0, r4, lr} 172 | /* Making room for r5-r11 which will be spilled later */ 173 | .pad #28 174 | sub sp, sp, #28 175 | 176 | // preload the destination because we'll align it to a cache line 177 | // with small writes. Also start the source "pump". 178 | PLD (r0, #0) 179 | PLD (r1, #0) 180 | PLD (r1, #32) 181 | 182 | /* it simplifies things to take care of len<4 early */ 183 | cmp r2, #4 184 | blo copy_last_3_and_return 185 | 186 | /* compute the offset to align the source 187 | * offset = (4-(src&3))&3 = -src & 3 188 | */ 189 | rsb r3, r1, #0 190 | ands r3, r3, #3 191 | beq src_aligned 192 | 193 | /* align source to 32 bits. We need to insert 2 instructions between 194 | * a ldr[b|h] and str[b|h] because byte and half-word instructions 195 | * stall 2 cycles. 196 | */ 197 | movs r12, r3, lsl #31 198 | sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */ 199 | ldrmib r3, [r1], #1 200 | ldrcsb r4, [r1], #1 201 | ldrcsb r12,[r1], #1 202 | strmib r3, [r0], #1 203 | strcsb r4, [r0], #1 204 | strcsb r12,[r0], #1 205 | 206 | src_aligned: 207 | 208 | /* see if src and dst are aligned together (congruent) */ 209 | eor r12, r0, r1 210 | tst r12, #3 211 | bne non_congruent 212 | 213 | /* Use post-incriment mode for stm to spill r5-r11 to reserved stack 214 | * frame. Don't update sp. 215 | */ 216 | stmea sp, {r5-r11} 217 | 218 | /* align the destination to a cache-line */ 219 | rsb r3, r0, #0 220 | ands r3, r3, #0x1C 221 | beq congruent_aligned32 222 | cmp r3, r2 223 | andhi r3, r2, #0x1C 224 | 225 | /* conditionnaly copies 0 to 7 words (length in r3) */ 226 | movs r12, r3, lsl #28 227 | ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ 228 | ldmmiia r1!, {r8, r9} /* 8 bytes */ 229 | stmcsia r0!, {r4, r5, r6, r7} 230 | stmmiia r0!, {r8, r9} 231 | tst r3, #0x4 232 | ldrne r10,[r1], #4 /* 4 bytes */ 233 | strne r10,[r0], #4 234 | sub r2, r2, r3 235 | 236 | congruent_aligned32: 237 | /* 238 | * here source is aligned to 32 bytes. 239 | */ 240 | 241 | cached_aligned32: 242 | subs r2, r2, #32 243 | blo less_than_32_left 244 | 245 | /* 246 | * We preload a cache-line up to 64 bytes ahead. On the 926, this will 247 | * stall only until the requested world is fetched, but the linefill 248 | * continues in the the background. 249 | * While the linefill is going, we write our previous cache-line 250 | * into the write-buffer (which should have some free space). 251 | * When the linefill is done, the writebuffer will 252 | * start dumping its content into memory 253 | * 254 | * While all this is going, we then load a full cache line into 255 | * 8 registers, this cache line should be in the cache by now 256 | * (or partly in the cache). 257 | * 258 | * This code should work well regardless of the source/dest alignment. 259 | * 260 | */ 261 | 262 | // Align the preload register to a cache-line because the cpu does 263 | // "critical word first" (the first word requested is loaded first). 264 | bic r12, r1, #0x1F 265 | add r12, r12, #64 266 | 267 | 1: ldmia r1!, { r4-r11 } 268 | PLD (r12, #64) 269 | subs r2, r2, #32 270 | 271 | // NOTE: if r12 is more than 64 ahead of r1, the following ldrhi 272 | // for ARM9 preload will not be safely guarded by the preceding subs. 273 | // When it is safely guarded the only possibility to have SIGSEGV here 274 | // is because the caller overstates the length. 275 | ldrhi r3, [r12], #32 /* cheap ARM9 preload */ 276 | stmia r0!, { r4-r11 } 277 | bhs 1b 278 | 279 | add r2, r2, #32 280 | 281 | 282 | 283 | 284 | less_than_32_left: 285 | /* 286 | * less than 32 bytes left at this point (length in r2) 287 | */ 288 | 289 | /* skip all this if there is nothing to do, which should 290 | * be a common case (if not executed the code below takes 291 | * about 16 cycles) 292 | */ 293 | tst r2, #0x1F 294 | beq 1f 295 | 296 | /* conditionnaly copies 0 to 31 bytes */ 297 | movs r12, r2, lsl #28 298 | ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */ 299 | ldmmiia r1!, {r8, r9} /* 8 bytes */ 300 | stmcsia r0!, {r4, r5, r6, r7} 301 | stmmiia r0!, {r8, r9} 302 | movs r12, r2, lsl #30 303 | ldrcs r3, [r1], #4 /* 4 bytes */ 304 | ldrmih r4, [r1], #2 /* 2 bytes */ 305 | strcs r3, [r0], #4 306 | strmih r4, [r0], #2 307 | tst r2, #0x1 308 | ldrneb r3, [r1] /* last byte */ 309 | strneb r3, [r0] 310 | 311 | /* we're done! restore everything and return */ 312 | 1: ldmfd sp!, {r5-r11} 313 | ldmfd sp!, {r0, r4, lr} 314 | bx lr 315 | 316 | /********************************************************************/ 317 | 318 | non_congruent: 319 | /* 320 | * here source is aligned to 4 bytes 321 | * but destination is not. 322 | * 323 | * in the code below r2 is the number of bytes read 324 | * (the number of bytes written is always smaller, because we have 325 | * partial words in the shift queue) 326 | */ 327 | cmp r2, #4 328 | blo copy_last_3_and_return 329 | 330 | /* Use post-incriment mode for stm to spill r5-r11 to reserved stack 331 | * frame. Don't update sp. 332 | */ 333 | stmea sp, {r5-r11} 334 | 335 | /* compute shifts needed to align src to dest */ 336 | rsb r5, r0, #0 337 | and r5, r5, #3 /* r5 = # bytes in partial words */ 338 | mov r12, r5, lsl #3 /* r12 = right */ 339 | rsb lr, r12, #32 /* lr = left */ 340 | 341 | /* read the first word */ 342 | ldr r3, [r1], #4 343 | sub r2, r2, #4 344 | 345 | /* write a partial word (0 to 3 bytes), such that destination 346 | * becomes aligned to 32 bits (r5 = nb of words to copy for alignment) 347 | */ 348 | movs r5, r5, lsl #31 349 | strmib r3, [r0], #1 350 | movmi r3, r3, lsr #8 351 | strcsb r3, [r0], #1 352 | movcs r3, r3, lsr #8 353 | strcsb r3, [r0], #1 354 | movcs r3, r3, lsr #8 355 | 356 | cmp r2, #4 357 | blo partial_word_tail 358 | 359 | /* Align destination to 32 bytes (cache line boundary) */ 360 | 1: tst r0, #0x1c 361 | beq 2f 362 | ldr r5, [r1], #4 363 | sub r2, r2, #4 364 | orr r4, r3, r5, lsl lr 365 | mov r3, r5, lsr r12 366 | str r4, [r0], #4 367 | cmp r2, #4 368 | bhs 1b 369 | blo partial_word_tail 370 | 371 | /* copy 32 bytes at a time */ 372 | 2: subs r2, r2, #32 373 | blo less_than_thirtytwo 374 | 375 | /* Use immediate mode for the shifts, because there is an extra cycle 376 | * for register shifts, which could account for up to 50% of 377 | * performance hit. 378 | */ 379 | 380 | cmp r12, #24 381 | beq loop24 382 | cmp r12, #8 383 | beq loop8 384 | 385 | loop16: 386 | ldr r12, [r1], #4 387 | 1: mov r4, r12 388 | ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} 389 | PLD (r1, #64) 390 | subs r2, r2, #32 391 | ldrhs r12, [r1], #4 392 | orr r3, r3, r4, lsl #16 393 | mov r4, r4, lsr #16 394 | orr r4, r4, r5, lsl #16 395 | mov r5, r5, lsr #16 396 | orr r5, r5, r6, lsl #16 397 | mov r6, r6, lsr #16 398 | orr r6, r6, r7, lsl #16 399 | mov r7, r7, lsr #16 400 | orr r7, r7, r8, lsl #16 401 | mov r8, r8, lsr #16 402 | orr r8, r8, r9, lsl #16 403 | mov r9, r9, lsr #16 404 | orr r9, r9, r10, lsl #16 405 | mov r10, r10, lsr #16 406 | orr r10, r10, r11, lsl #16 407 | stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} 408 | mov r3, r11, lsr #16 409 | bhs 1b 410 | b less_than_thirtytwo 411 | 412 | loop8: 413 | ldr r12, [r1], #4 414 | 1: mov r4, r12 415 | ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} 416 | PLD (r1, #64) 417 | subs r2, r2, #32 418 | ldrhs r12, [r1], #4 419 | orr r3, r3, r4, lsl #24 420 | mov r4, r4, lsr #8 421 | orr r4, r4, r5, lsl #24 422 | mov r5, r5, lsr #8 423 | orr r5, r5, r6, lsl #24 424 | mov r6, r6, lsr #8 425 | orr r6, r6, r7, lsl #24 426 | mov r7, r7, lsr #8 427 | orr r7, r7, r8, lsl #24 428 | mov r8, r8, lsr #8 429 | orr r8, r8, r9, lsl #24 430 | mov r9, r9, lsr #8 431 | orr r9, r9, r10, lsl #24 432 | mov r10, r10, lsr #8 433 | orr r10, r10, r11, lsl #24 434 | stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} 435 | mov r3, r11, lsr #8 436 | bhs 1b 437 | b less_than_thirtytwo 438 | 439 | loop24: 440 | ldr r12, [r1], #4 441 | 1: mov r4, r12 442 | ldmia r1!, { r5,r6,r7, r8,r9,r10,r11} 443 | PLD (r1, #64) 444 | subs r2, r2, #32 445 | ldrhs r12, [r1], #4 446 | orr r3, r3, r4, lsl #8 447 | mov r4, r4, lsr #24 448 | orr r4, r4, r5, lsl #8 449 | mov r5, r5, lsr #24 450 | orr r5, r5, r6, lsl #8 451 | mov r6, r6, lsr #24 452 | orr r6, r6, r7, lsl #8 453 | mov r7, r7, lsr #24 454 | orr r7, r7, r8, lsl #8 455 | mov r8, r8, lsr #24 456 | orr r8, r8, r9, lsl #8 457 | mov r9, r9, lsr #24 458 | orr r9, r9, r10, lsl #8 459 | mov r10, r10, lsr #24 460 | orr r10, r10, r11, lsl #8 461 | stmia r0!, {r3,r4,r5,r6, r7,r8,r9,r10} 462 | mov r3, r11, lsr #24 463 | bhs 1b 464 | 465 | 466 | less_than_thirtytwo: 467 | /* copy the last 0 to 31 bytes of the source */ 468 | rsb r12, lr, #32 /* we corrupted r12, recompute it */ 469 | add r2, r2, #32 470 | cmp r2, #4 471 | blo partial_word_tail 472 | 473 | 1: ldr r5, [r1], #4 474 | sub r2, r2, #4 475 | orr r4, r3, r5, lsl lr 476 | mov r3, r5, lsr r12 477 | str r4, [r0], #4 478 | cmp r2, #4 479 | bhs 1b 480 | 481 | partial_word_tail: 482 | /* we have a partial word in the input buffer */ 483 | movs r5, lr, lsl #(31-3) 484 | strmib r3, [r0], #1 485 | movmi r3, r3, lsr #8 486 | strcsb r3, [r0], #1 487 | movcs r3, r3, lsr #8 488 | strcsb r3, [r0], #1 489 | 490 | /* Refill spilled registers from the stack. Don't update sp. */ 491 | ldmfd sp, {r5-r11} 492 | 493 | copy_last_3_and_return: 494 | movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */ 495 | ldrmib r2, [r1], #1 496 | ldrcsb r3, [r1], #1 497 | ldrcsb r12,[r1] 498 | strmib r2, [r0], #1 499 | strcsb r3, [r0], #1 500 | strcsb r12,[r0] 501 | 502 | /* we're done! restore sp and spilled registers and return */ 503 | add sp, sp, #28 504 | ldmfd sp!, {r0, r4, lr} 505 | bx lr 506 | .fnend 507 | 508 | 509 | #endif /* __ARM_ARCH__ < 7 */ 510 | -------------------------------------------------------------------------------- /multimeter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * read data from TekPower TP4000ZC 3 | * 4 | * See http://xuth.net/programming/tp4000zc/tp4000zc.py for details. 5 | * Also http://xuth.net/programming/tp4000zc/tp4000zc_serial_protocol.jpg 6 | * 7 | */ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | static bool volatile doExit = false ; 19 | 20 | static void ctrlcHandler( int signo ) { 21 | printf( "\r\n" ); 22 | doExit = true ; 23 | } 24 | 25 | struct value_to_char { 26 | unsigned char v; 27 | char c ; 28 | }; 29 | 30 | static struct value_to_char translations[] = { 31 | {0x05, '1'} 32 | , {0x5b, '2'} 33 | , {0x1f, '3'} 34 | , {0x27, '4'} 35 | , {0x3e, '5'} 36 | , {0x7e, '6'} 37 | , {0x15, '7'} 38 | , {0x7f, '8'} 39 | , {0x3f, '9'} 40 | , {0x7d, '0'} 41 | , {0x68, 'L'} 42 | , {0x00, ' '} 43 | }; 44 | 45 | static unsigned num_translations = sizeof(translations)/sizeof(translations[0]); 46 | 47 | static char translate(unsigned char v) { 48 | for (int i = 0; i < num_translations; i++) { 49 | if (translations[i].v == v) { 50 | return translations[i].c; 51 | } 52 | } 53 | return '?'; 54 | } 55 | 56 | static void process(unsigned char const *inData, unsigned char len) 57 | { 58 | #if 0 59 | printf("%2u: ", len); 60 | for(int i=0; i < len; i++) { 61 | printf("%02x ", inData[i]); 62 | } 63 | printf("\n"); 64 | fflush(stdout); 65 | #endif 66 | if (14 == len) { 67 | /* sanity check sequence numbers */ 68 | for (int i=0; i < len; i++) { 69 | if (i+1 != (inData[i]>>4)) { 70 | printf("invalid seq\n"); 71 | return; 72 | } 73 | } 74 | #if 0 75 | bool flags[4]; 76 | unsigned char digits[4]; 77 | for (int i=0; i < 4; i++) { 78 | flags[i] = (0 != (inData[2*i+1]&0x08)); 79 | digits[i] = ((inData[2*i+1]&0x07)<<4) 80 | | (inData[2*i+2]&0x0F); 81 | } 82 | for (int i=0; i < 4; i++) { 83 | if (flags[i]) 84 | fputc('.',stdout); 85 | fputc(translate(digits[i]),stdout); 86 | } 87 | printf("\n"); fflush(stdout); 88 | #endif 89 | char outBuf[80]; 90 | int outLen = 0; 91 | for (int i=0; i < 4; i++) { 92 | if(0 != (inData[2*i+1]&0x08)) 93 | outBuf[outLen++] = '.'; 94 | unsigned char v = ((inData[2*i+1]&0x07)<<4) 95 | | (inData[2*i+2]&0x0F); 96 | outBuf[outLen++] = translate(v); 97 | } 98 | outBuf[outLen] = '\0'; 99 | int start; 100 | for (start = 0; start < outLen; start++) { 101 | if ('0' != outBuf[start]) 102 | break; 103 | } 104 | double dub ; 105 | if (1 == sscanf(outBuf+start,"%lf",&dub)) { 106 | printf("%.2lf\n", dub); 107 | fflush(stdout); 108 | } 109 | // printf("%s\n",outBuf+start); fflush(stdout); 110 | } 111 | } 112 | 113 | int main( int argc, char const * const argv[]) 114 | { 115 | if (1 == argc) { 116 | fprintf(stderr, "Usage: %s device\n", 117 | argv[0]); 118 | return -1; 119 | } 120 | int const fdSerial = open(argv[1], O_RDWR); 121 | if(0 > fdSerial) { 122 | perror(argv[1]); 123 | return -1; 124 | } 125 | fcntl(fdSerial, F_SETFD, FD_CLOEXEC); 126 | fcntl(fdSerial, F_SETFL, O_NONBLOCK); 127 | struct termios oldSerialState; 128 | 129 | tcgetattr(fdSerial, &oldSerialState); 130 | struct termios newState = oldSerialState; 131 | newState.c_cc[VMIN] = 1; 132 | cfsetispeed(&newState, B2400); 133 | cfsetospeed(&newState, B2400); 134 | newState.c_cc[VTIME] = 0; 135 | newState.c_cflag &= ~(PARENB|CSTOPB|CSIZE|CRTSCTS); 136 | newState.c_cflag |= (CLOCAL | CREAD |CS8); // Select 8 data bits 137 | newState.c_lflag &= ~(ICANON | ECHO ); // set raw mode for input 138 | newState.c_iflag &= ~(IXON | IXOFF | IXANY|INLCR|ICRNL|IUCLC); //no software flow control 139 | newState.c_oflag &= ~OPOST; //raw output 140 | tcsetattr(fdSerial, TCSANOW, &newState); 141 | 142 | pollfd fds[1]; 143 | fds[0].fd = fdSerial ; 144 | fds[0].events = POLLIN | POLLERR ; 145 | 146 | signal(SIGINT, ctrlcHandler); 147 | 148 | int timeout= -1; 149 | unsigned char inBuf[256]; 150 | unsigned char inLength = 0; 151 | 152 | while( !doExit ) { 153 | int const numReady = ::poll(fds, 2, timeout); 154 | if( 0 < numReady ) { 155 | if (fds[0].revents & POLLIN) { 156 | int numRead = read(fds[0].fd, 157 | inBuf+inLength, 158 | sizeof(inBuf)-inLength); 159 | if (0 < numRead) { 160 | inLength += numRead; 161 | if (inLength == sizeof(inBuf)) { 162 | process(inBuf,inLength); 163 | inLength = 0; 164 | } 165 | timeout = 1; 166 | } 167 | } 168 | else if(inLength){ 169 | process(inBuf,inLength); 170 | inLength = 0; 171 | timeout=-1; 172 | } 173 | if (fds[0].revents & POLLERR) 174 | printf("err\n"); 175 | } 176 | else if(inLength){ 177 | process(inBuf,inLength); 178 | inLength = 0; 179 | timeout=-1; 180 | } 181 | } 182 | 183 | tcsetattr( fdSerial, TCSANOW, &oldSerialState ); 184 | 185 | close( fdSerial ); 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /ov5640: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boundarydevices/imx-utils/71468fa21be4af67c39f9fec32cf558bdc563bb6/ov5640 -------------------------------------------------------------------------------- /physMem.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Module physMem.cpp 3 | * 4 | * This module defines ... 5 | * 6 | * 7 | * Change History : 8 | * 9 | * $Log: physMem.cpp,v $ 10 | * Revision 1.2 2009-05-14 16:28:16 ericn 11 | * [physMem] Ensure munmap in destructor 12 | * 13 | * Revision 1.1 2008-06-25 01:20:47 ericn 14 | * -import 15 | * 16 | * 17 | * Copyright Boundary Devices, Inc. 2007 18 | */ 19 | 20 | 21 | #include "physMem.h" 22 | #include 23 | #include 24 | #include 25 | 26 | #define MAP_SHIFT 12 27 | #define MAP_SIZE (1<> MAP_SHIFT ; 42 | unsigned lastPage = (physAddr+size-1) >> MAP_SHIFT ; 43 | unsigned mapSize = (lastPage-startPage+1)< 74 | #include 75 | #include "hexDump.h" 76 | #include 77 | 78 | static bool deposit = 0 ; 79 | static bool binary = 0 ; 80 | static unsigned long value = 0 ; 81 | 82 | static void parseArgs( int &argc, char const **argv ) 83 | { 84 | for( unsigned arg = 1 ; arg < argc ; arg++ ){ 85 | if( '-' == *argv[arg] ){ 86 | char const *param = argv[arg]+1 ; 87 | if( 'd' == tolower(*param) ){ 88 | deposit = true ; 89 | value = strtoul(param+1,0,16); 90 | } else if( 'b' == tolower(*param) ){ 91 | binary = true ; 92 | fflush(stdout); 93 | } 94 | else 95 | printf( "unknown option %s\n", param ); 96 | 97 | // pull from argument list 98 | for( int j = arg+1 ; j < argc ; j++ ){ 99 | argv[j-1] = argv[j]; 100 | } 101 | --arg ; 102 | --argc ; 103 | } 104 | } 105 | } 106 | 107 | int main( int argc, char const *argv[] ) 108 | { 109 | parseArgs(argc,argv); 110 | if( 1 < argc ){ 111 | unsigned long address = strtoul( argv[1], 0, 0 ); 112 | unsigned length ; 113 | if( 2 < argc ) 114 | length = strtoul( argv[2], 0, 0 ); 115 | else 116 | length = 512 ; 117 | 118 | physMem_t phys(address, length, deposit ? O_RDWR : O_RDONLY ); 119 | if( phys.worked() ) 120 | { 121 | if( deposit ){ 122 | unsigned long *longs = (unsigned long *)phys.ptr(); 123 | printf( "depositing 0x%08lx\n", value ); 124 | while (0 < length) { 125 | *longs++ = value ; 126 | length -= sizeof(*longs); 127 | } 128 | } 129 | if(!binary){ 130 | hexDumper_t dump( phys.ptr(), length, address ); 131 | while( dump.nextLine() ) 132 | printf( "%s\n", dump.getLine() ); 133 | } 134 | else { 135 | write(1, phys.ptr(), length); 136 | fflush(stdout); 137 | } 138 | } 139 | else 140 | perror( "map" ); 141 | } 142 | else 143 | fprintf( stderr, "Usage: %s address [length=512]\n", argv[0] ); 144 | return 0 ; 145 | } 146 | #endif 147 | -------------------------------------------------------------------------------- /physMem.h: -------------------------------------------------------------------------------- 1 | #ifndef __PHYSMEM_H__ 2 | #define __PHYSMEM_H__ "$Id: physMem.h,v 1.2 2009-05-14 16:28:16 ericn Exp $" 3 | 4 | /* 5 | * physMem.h 6 | * 7 | * This header file declares the physMem_t class, 8 | * which can be used to read [and write] a section 9 | * of physical memory (use with care!). 10 | * 11 | * Change History : 12 | * 13 | * $Log: physMem.h,v $ 14 | * Revision 1.2 2009-05-14 16:28:16 ericn 15 | * [physMem] Ensure munmap in destructor 16 | * 17 | * Revision 1.1 2008-06-25 01:20:47 ericn 18 | * -import 19 | * 20 | * 21 | * 22 | * Copyright Boundary Devices, Inc. 2007 23 | */ 24 | 25 | #include 26 | 27 | class physMem_t { 28 | public: 29 | physMem_t( unsigned long physAddr, unsigned long size, unsigned long mode = O_RDONLY ); 30 | ~physMem_t( void ); 31 | 32 | bool worked() const { return 0 <= fd_ ; } 33 | 34 | void *ptr() const { return mem_ ; } 35 | 36 | void invalidate(); 37 | 38 | private: 39 | int fd_ ; 40 | void *map_ ; // start of page 41 | void *mem_ ; // start of data 42 | unsigned mapSize_ ; 43 | }; 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /savembrs.c: -------------------------------------------------------------------------------- 1 | #define _LARGEFILE64_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define BLOCKSIZE 512 11 | #define BLOCKSPERFLASH 300000 12 | 13 | static unsigned char msdos_mbr[2] = { 14 | 0x55, 0xaa 15 | }; 16 | 17 | static const char *const i386_sys_types[] = { 18 | "\x00" "Empty", 19 | "\x01" "FAT12", 20 | "\x04" "FAT16 <32M", 21 | "\x05" "Extended", /* DOS 3.3+ extended partition */ 22 | #define EXTENDED_PARTITION 5 23 | "\x06" "FAT16", /* DOS 16-bit >=32M */ 24 | "\x07" "HPFS/NTFS", /* OS/2 IFS, eg, HPFS or NTFS or QNX */ 25 | "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */ 26 | "\x0b" "Win95 FAT32", 27 | "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */ 28 | "\x0e" "Win95 FAT16 (LBA)", 29 | "\x0f" "Win95 Ext'd (LBA)", 30 | "\x11" "Hidden FAT12", 31 | "\x12" "Compaq diagnostics", 32 | "\x14" "Hidden FAT16 <32M", 33 | "\x16" "Hidden FAT16", 34 | "\x17" "Hidden HPFS/NTFS", 35 | "\x1b" "Hidden Win95 FAT32", 36 | "\x1c" "Hidden W95 FAT32 (LBA)", 37 | "\x1e" "Hidden W95 FAT16 (LBA)", 38 | "\x3c" "Part.Magic recovery", 39 | "\x41" "PPC PReP Boot", 40 | "\x42" "SFS", 41 | "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ 42 | "\x80" "Old Minix", /* Minix 1.4a and earlier */ 43 | "\x81" "Minix / old Linux",/* Minix 1.4b and later */ 44 | "\x82" "Linux swap", /* also Solaris */ 45 | "\x83" "Linux", 46 | "\x84" "OS/2 hidden C: drive", 47 | "\x85" "Linux extended", 48 | "\x86" "NTFS volume set", 49 | "\x87" "NTFS volume set", 50 | "\x8e" "Linux LVM", 51 | "\x9f" "BSD/OS", /* BSDI */ 52 | "\xa0" "Thinkpad hibernation", 53 | "\xa5" "FreeBSD", /* various BSD flavours */ 54 | "\xa6" "OpenBSD", 55 | "\xa8" "Darwin UFS", 56 | "\xa9" "NetBSD", 57 | "\xab" "Darwin boot", 58 | "\xb7" "BSDI fs", 59 | "\xb8" "BSDI swap", 60 | "\xbe" "Solaris boot", 61 | "\xeb" "BeOS fs", 62 | "\xee" "EFI GPT", /* Intel EFI GUID Partition Table */ 63 | "\xef" "EFI (FAT-12/16/32)", /* Intel EFI System Partition */ 64 | "\xf0" "Linux/PA-RISC boot", /* Linux/PA-RISC boot loader */ 65 | "\xf2" "DOS secondary", /* DOS 3.3+ secondary */ 66 | "\xfd" "Linux raid autodetect", /* New (2.2.x) raid partition with 67 | autodetect using persistent 68 | superblock */ 69 | #if 0 /* ENABLE_WEIRD_PARTITION_TYPES */ 70 | "\x02" "XENIX root", 71 | "\x03" "XENIX usr", 72 | "\x08" "AIX", /* AIX boot (AIX -- PS/2 port) or SplitDrive */ 73 | "\x09" "AIX bootable", /* AIX data or Coherent */ 74 | "\x10" "OPUS", 75 | "\x18" "AST SmartSleep", 76 | "\x24" "NEC DOS", 77 | "\x39" "Plan 9", 78 | "\x40" "Venix 80286", 79 | "\x4d" "QNX4.x", 80 | "\x4e" "QNX4.x 2nd part", 81 | "\x4f" "QNX4.x 3rd part", 82 | "\x50" "OnTrack DM", 83 | "\x51" "OnTrack DM6 Aux1", /* (or Novell) */ 84 | "\x52" "CP/M", /* CP/M or Microport SysV/AT */ 85 | "\x53" "OnTrack DM6 Aux3", 86 | "\x54" "OnTrackDM6", 87 | "\x55" "EZ-Drive", 88 | "\x56" "Golden Bow", 89 | "\x5c" "Priam Edisk", 90 | "\x61" "SpeedStor", 91 | "\x64" "Novell Netware 286", 92 | "\x65" "Novell Netware 386", 93 | "\x70" "DiskSecure Multi-Boot", 94 | "\x75" "PC/IX", 95 | "\x93" "Amoeba", 96 | "\x94" "Amoeba BBT", /* (bad block table) */ 97 | "\xa7" "NeXTSTEP", 98 | "\xbb" "Boot Wizard hidden", 99 | "\xc1" "DRDOS/sec (FAT-12)", 100 | "\xc4" "DRDOS/sec (FAT-16 < 32M)", 101 | "\xc6" "DRDOS/sec (FAT-16)", 102 | "\xc7" "Syrinx", 103 | "\xda" "Non-FS data", 104 | "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or 105 | Concurrent DOS or CTOS */ 106 | "\xde" "Dell Utility", /* Dell PowerEdge Server utilities */ 107 | "\xdf" "BootIt", /* BootIt EMBRM */ 108 | "\xe1" "DOS access", /* DOS access or SpeedStor 12-bit FAT 109 | extended partition */ 110 | "\xe3" "DOS R/O", /* DOS R/O or SpeedStor */ 111 | "\xe4" "SpeedStor", /* SpeedStor 16-bit FAT extended 112 | partition < 1024 cyl. */ 113 | "\xf1" "SpeedStor", 114 | "\xf4" "SpeedStor", /* SpeedStor large partition */ 115 | "\xfe" "LANstep", /* SpeedStor >1024 cyl. or LANstep */ 116 | "\xff" "BBT", /* Xenix Bad Block Table */ 117 | #endif 118 | NULL 119 | }; 120 | 121 | static char const *find_part_type(unsigned char t) 122 | { 123 | char const *const*type = i386_sys_types ; 124 | while (*type){ 125 | if (t == (unsigned char)(*type)[0]) { 126 | return (*type)+1 ; 127 | } 128 | type++; 129 | } 130 | return "unknown" ; 131 | } 132 | 133 | /* based on linux/include/genhd.h */ 134 | struct partition { 135 | unsigned char boot_ind; /* 0x80 - active */ 136 | unsigned char head; /* starting head */ 137 | unsigned char sector; /* starting sector */ 138 | unsigned char cyl; /* starting cylinder */ 139 | unsigned char sys_ind; /* What partition type */ 140 | unsigned char end_head; /* end head */ 141 | unsigned char end_sector; /* end sector */ 142 | unsigned char end_cyl; /* end cylinder */ 143 | unsigned char start_sect[4]; /* starting sector counting from 0 */ 144 | unsigned char nr_sects[4]; /* nr of sectors in partition */ 145 | } __attribute__ ((packed)); 146 | 147 | struct mbr { 148 | unsigned char boot_code[440]; 149 | unsigned char disk_signature[4]; 150 | unsigned char padding[2]; 151 | struct partition partition_record[4]; 152 | unsigned char mbr_signature[2]; 153 | } __attribute__ ((packed)); 154 | 155 | #define ARRAY_SIZE(__arr) ((sizeof(__arr))/sizeof((__arr)[0])) 156 | 157 | static unsigned mbrs[128] = { 158 | 0 159 | }; 160 | static unsigned num_mbrs = 1; 161 | static unsigned firstext = 0 ; 162 | 163 | struct part_lba { 164 | unsigned partnum ; 165 | unsigned startsect ; 166 | unsigned count ; 167 | }; 168 | 169 | static struct part_lba save_parts[128] = { 170 | 0 171 | }; 172 | static unsigned numsaveparts = 0 ; 173 | 174 | static void saveMBR(unsigned offs, char *mbrbuf) 175 | { 176 | int fdout ; 177 | char fname[512]; 178 | snprintf(fname, sizeof(fname),"mbr%u",offs); 179 | fdout = open(fname,O_WRONLY|O_CREAT|O_EXCL,0666); 180 | if (0 > fdout) { 181 | perror(fname); 182 | exit(-1); 183 | } 184 | write(fdout,mbrbuf,BLOCKSIZE); 185 | close(fdout); 186 | printf("fastboot flash mmc0:%u %s\n", offs, fname); 187 | } 188 | 189 | static void savePart(int fddisk, unsigned pnum, unsigned start, unsigned count) 190 | { 191 | unsigned offs = 0 ; 192 | unsigned const startstart = start ; 193 | while (0 < count) { 194 | int fdout ; 195 | char fname[512]; 196 | int blocks = 0 ; 197 | snprintf(fname, sizeof(fname),"part%u.%u",pnum,offs); 198 | fdout = open(fname,O_WRONLY|O_CREAT|O_EXCL,0666); 199 | if (0 > fdout) { 200 | perror(fname); 201 | exit(-1); 202 | } 203 | printf("fastboot flash mmc0:%u %s\n", start, fname); 204 | while ((0 blocks)) { 205 | unsigned char blockbuf[BLOCKSIZE]; 206 | off64_t pos = (off64_t)start*BLOCKSIZE; 207 | if (pos != lseek64(fddisk,pos,SEEK_SET)) { 208 | perror("seek"); 209 | exit(-1); 210 | } 211 | if (BLOCKSIZE != read(fddisk,blockbuf,sizeof(blockbuf))) { 212 | perror("read"); 213 | exit(-1); 214 | } 215 | if (BLOCKSIZE != write(fdout,blockbuf,sizeof(blockbuf))) { 216 | perror("write"); 217 | exit(-1); 218 | } 219 | start++; 220 | blocks++; 221 | count--; 222 | } 223 | offs++ ; 224 | close(fdout); 225 | } 226 | } 227 | 228 | int main (int argc, char **argv) 229 | { 230 | int do_save ; 231 | unsigned pcount = 0 ; 232 | int fd; 233 | if (1 >= argc) { 234 | fprintf(stderr, "Usage: %s /path/to/disk [-d]\n", argv[0]); 235 | return -1 ; 236 | } 237 | 238 | fd = open(argv[1],O_RDONLY); 239 | if (0 > fd) { 240 | perror(argv[1]); 241 | return -1 ; 242 | } 243 | do_save = (2 < argc) && (0 == strcasecmp("-d",argv[2])); 244 | while (0 < num_mbrs) { 245 | int i; 246 | int numread; 247 | char mbrbuf[BLOCKSIZE]; 248 | unsigned start = mbrs[0]; 249 | off64_t pos = (off64_t)start*sizeof(mbrbuf); 250 | --num_mbrs ; 251 | if (0 < num_mbrs) { 252 | memmove(mbrs,mbrs+1,num_mbrs*sizeof(mbrs[0])); 253 | } 254 | if (pos != lseek64(fd,pos,SEEK_SET)) { 255 | perror("seek"); 256 | return -1 ; 257 | } 258 | numread = read(fd,mbrbuf,sizeof(mbrbuf)); 259 | if (sizeof(mbrbuf) != numread) { 260 | perror ("read"); 261 | return -1 ; 262 | } 263 | struct mbr *pmbr = (struct mbr *)mbrbuf; 264 | if (0 != memcmp(msdos_mbr,pmbr->mbr_signature,sizeof(msdos_mbr))) { 265 | fprintf(stderr, "Invalid signature %02x %02x in MBR %x\n", 266 | pmbr->mbr_signature[0],pmbr->mbr_signature[1],start); 267 | return -1 ; 268 | } 269 | saveMBR(start,mbrbuf); 270 | for (i = 0 ; i < ARRAY_SIZE(pmbr->partition_record); i++) { 271 | struct partition *part = pmbr->partition_record+i; 272 | unsigned pstart, pend ; 273 | memcpy(&pstart, part->start_sect, sizeof(pstart)); 274 | memcpy(&pend, part->nr_sects, sizeof(pend)); 275 | pend += pstart-1; 276 | 277 | if ((0 != part->sys_ind) 278 | && 279 | (EXTENDED_PARTITION != part->sys_ind)) { 280 | unsigned numsect = pend-pstart+1; 281 | unsigned numbytes = numsect*512; 282 | unsigned mb = numbytes>>20; 283 | printf("# %cp%u\t%12u\t%12u\t%12u\t%12u bytes\t%5u MB\t%s\n", 284 | (part->boot_ind&0x80)?'*':' ', 285 | pcount+1, 286 | start+pstart, start+pend, 287 | numsect, numbytes, mb, 288 | find_part_type(part->sys_ind)); 289 | if (do_save) { 290 | save_parts[numsaveparts].partnum = pcount+1 ; 291 | save_parts[numsaveparts].startsect = start+pstart; 292 | save_parts[numsaveparts].count = pend-pstart+1 ; 293 | ++numsaveparts ; 294 | } 295 | } 296 | if(EXTENDED_PARTITION == part->sys_ind) { 297 | mbrs[num_mbrs++] = pstart+firstext; 298 | if (0 == firstext) { 299 | firstext = pstart ; 300 | } 301 | } 302 | if ((0 == start) 303 | || 304 | ((EXTENDED_PARTITION != part->sys_ind) 305 | && 306 | (0 != part->sys_ind))) { 307 | pcount++ ; 308 | } 309 | } 310 | } 311 | if (0 < numsaveparts) { 312 | int i ; 313 | printf ("# %s: restore %u parts here\n", argv[0],numsaveparts); 314 | for (i = 0 ; i < numsaveparts ; i++) { 315 | printf("# p%d: %u.%u\n" 316 | , save_parts[i].partnum 317 | , save_parts[i].startsect 318 | , save_parts[i].count); 319 | savePart(fd 320 | , save_parts[i].partnum 321 | , save_parts[i].startsect 322 | , save_parts[i].count); 323 | } 324 | } 325 | close(fd); 326 | return 0 ; 327 | } 328 | -------------------------------------------------------------------------------- /spidev.h: -------------------------------------------------------------------------------- 1 | #ifndef __SPIDEV_H__ 2 | #define __SPIDEV_H__ 3 | 4 | /*---------------------------------------------------------------------------*/ 5 | /* IOCTL commands */ 6 | 7 | #define SPI_IOC_MAGIC 'k' 8 | 9 | /** 10 | * struct spi_ioc_transfer - describes a single SPI transfer 11 | * @tx_buf: Holds pointer to userspace buffer with transmit data, or null. 12 | * If no data is provided, zeroes are shifted out. 13 | * @rx_buf: Holds pointer to userspace buffer for receive data, or null. 14 | * @len: Length of tx and rx buffers, in bytes. 15 | * @speed_hz: Temporary override of the device's bitrate. 16 | * @bits_per_word: Temporary override of the device's wordsize. 17 | * @delay_usecs: If nonzero, how long to delay after the last bit transfer 18 | * before optionally deselecting the device before the next transfer. 19 | * @cs_change: True to deselect device before starting the next transfer. 20 | * 21 | * This structure is mapped directly to the kernel spi_transfer structure; 22 | * the fields have the same meanings, except of course that the pointers 23 | * are in a different address space (and may be of different sizes in some 24 | * cases, such as 32-bit i386 userspace over a 64-bit x86_64 kernel). 25 | * Zero-initialize the structure, including currently unused fields, to 26 | * accomodate potential future updates. 27 | * 28 | * SPI_IOC_MESSAGE gives userspace the equivalent of kernel spi_sync(). 29 | * Pass it an array of related transfers, they'll execute together. 30 | * Each transfer may be half duplex (either direction) or full duplex. 31 | * 32 | * struct spi_ioc_transfer mesg[4]; 33 | * ... 34 | * status = ioctl(fd, SPI_IOC_MESSAGE(4), mesg); 35 | * 36 | * So for example one transfer might send a nine bit command (right aligned 37 | * in a 16-bit word), the next could read a block of 8-bit data before 38 | * terminating that command by temporarily deselecting the chip; the next 39 | * could send a different nine bit command (re-selecting the chip), and the 40 | * last transfer might write some register values. 41 | */ 42 | struct spi_ioc_transfer { 43 | __u64 tx_buf; 44 | __u64 rx_buf; 45 | 46 | __u32 len; 47 | __u32 speed_hz; 48 | 49 | __u16 delay_usecs; 50 | __u8 bits_per_word; 51 | __u8 cs_change; 52 | __u32 pad; 53 | 54 | /* If the contents of 'struct spi_ioc_transfer' ever change 55 | * incompatibly, then the ioctl number (currently 0) must change; 56 | * ioctls with constant size fields get a bit more in the way of 57 | * error checking than ones (like this) where that field varies. 58 | * 59 | * NOTE: struct layout is the same in 64bit and 32bit userspace. 60 | */ 61 | }; 62 | 63 | /* not all platforms use or _IOC_TYPECHECK() ... */ 64 | #define SPI_MSGSIZE(N) \ 65 | ((((N)*(sizeof (struct spi_ioc_transfer))) < (1 << _IOC_SIZEBITS)) \ 66 | ? ((N)*(sizeof (struct spi_ioc_transfer))) : 0) 67 | #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)]) 68 | 69 | 70 | /* Read / Write of SPI mode (SPI_MODE_0..SPI_MODE_3) */ 71 | #define SPI_IOC_RD_MODE _IOR(SPI_IOC_MAGIC, 1, __u8) 72 | #define SPI_IOC_WR_MODE _IOW(SPI_IOC_MAGIC, 1, __u8) 73 | 74 | /* Read / Write SPI bit justification */ 75 | #define SPI_IOC_RD_LSB_FIRST _IOR(SPI_IOC_MAGIC, 2, __u8) 76 | #define SPI_IOC_WR_LSB_FIRST _IOW(SPI_IOC_MAGIC, 2, __u8) 77 | 78 | /* Read / Write SPI device word length (1..N) */ 79 | #define SPI_IOC_RD_BITS_PER_WORD _IOR(SPI_IOC_MAGIC, 3, __u8) 80 | #define SPI_IOC_WR_BITS_PER_WORD _IOW(SPI_IOC_MAGIC, 3, __u8) 81 | 82 | /* Read / Write SPI device default max speed hz */ 83 | #define SPI_IOC_RD_MAX_SPEED_HZ _IOR(SPI_IOC_MAGIC, 4, __u32) 84 | #define SPI_IOC_WR_MAX_SPEED_HZ _IOW(SPI_IOC_MAGIC, 4, __u32) 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /tickMs.h: -------------------------------------------------------------------------------- 1 | #ifndef __TICKMS_H__ 2 | #define __TICKMS_H__ "$Id: tickMs.h,v 1.4 2006-08-16 02:26:38 ericn Exp $" 3 | 4 | /* 5 | * tickMs.h 6 | * 7 | * This header file declares the tickMs() routine, 8 | * which returns a tick counter in milliseconds. 9 | * 10 | * 11 | * Change History : 12 | * 13 | * $Log: tickMs.h,v $ 14 | * Revision 1.4 2006-08-16 02:26:38 ericn 15 | * -add comparison operators for timeval 16 | * 17 | * Revision 1.3 2003/10/05 19:11:37 ericn 18 | * -added timeValToMs() call 19 | * 20 | * Revision 1.2 2003/08/11 00:10:43 ericn 21 | * -prevent #include dependency 22 | * 23 | * Revision 1.1 2003/07/27 15:19:12 ericn 24 | * -Initial import 25 | * 26 | * 27 | * 28 | * Copyright Boundary Devices, Inc. 2003 29 | */ 30 | 31 | #include 32 | 33 | inline long long timeValToMs( struct timeval const &tv ) 34 | { 35 | return ((long long)tv.tv_sec*1000)+((long long)tv.tv_usec / 1000 ); 36 | } 37 | 38 | inline long long tickMs() 39 | { 40 | struct timeval now ; gettimeofday( &now, 0 ); 41 | return timeValToMs( now ); 42 | } 43 | 44 | 45 | inline bool operator<( struct timeval const &lhs, 46 | struct timeval const &rhs ) 47 | { 48 | long int cmp = lhs.tv_sec-rhs.tv_sec ; 49 | if( 0 == cmp ) 50 | cmp = lhs.tv_usec - rhs.tv_usec ; 51 | 52 | return cmp < 0 ; 53 | } 54 | 55 | inline bool operator>( struct timeval const &lhs, 56 | struct timeval const &rhs ) 57 | { 58 | long int cmp = lhs.tv_sec-rhs.tv_sec ; 59 | if( 0 == cmp ) 60 | cmp = lhs.tv_usec - rhs.tv_usec ; 61 | 62 | return cmp > 0 ; 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /v4l_display.cpp: -------------------------------------------------------------------------------- 1 | #include "v4l_display.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | v4l_display_t::v4l_display_t 14 | ( unsigned picWidth, 15 | unsigned picHeight, 16 | Rect const &window, 17 | unsigned numframes ) 18 | : w(picWidth) 19 | , h(picHeight) 20 | , ysize(0) 21 | , ystride(0) 22 | , uvsize(0) 23 | , uvstride(0) 24 | , win(window) 25 | , nframes(numframes) 26 | , fd(-1) 27 | , bufs(0) 28 | , bufs_avail(0) 29 | , numQueued(0) 30 | , streaming(0) 31 | { 32 | memset(fbs,0,sizeof(fbs)); 33 | ystride = ((picWidth+7)/8)*8 ; 34 | ysize = h*ystride ; 35 | uvstride = ystride/2 ; 36 | uvsize = h*uvstride/2 ; 37 | 38 | int out = 3; 39 | int fd_fb = open("/dev/fb0", O_RDWR, 0); 40 | if (fd_fb < 0) { 41 | printf("unable to open fb0\n"); 42 | return ; 43 | } 44 | 45 | struct mxcfb_gbl_alpha alpha; 46 | alpha.alpha = 0; 47 | alpha.enable = 0; 48 | 49 | int err = ioctl(fd_fb, MXCFB_SET_GBL_ALPHA, &alpha); 50 | if (err < 0) { 51 | printf("set alpha blending failed\n"); 52 | return ; 53 | } 54 | 55 | struct mxcfb_gbl_alpha a ; 56 | a.enable = 1; 57 | a.alpha = 255 ; 58 | err = ioctl(fd_fb,MXCFB_SET_GBL_ALPHA,&a); 59 | if ( err ) { 60 | perror( "MXCFB_SET_GBL_ALPHA"); 61 | return ; 62 | } 63 | struct mxcfb_color_key key; 64 | key.enable = 1 ; 65 | key.color_key = 0 ; 66 | if (ioctl(fd_fb,MXCFB_SET_CLR_KEY, &key) <0) { 67 | perror("MXCFB_SET_CLR_KEY error!"); 68 | return ; 69 | } 70 | 71 | close (fd_fb); 72 | char v4l_device[32] = "/dev/video16"; 73 | fd = open(v4l_device, O_RDWR|O_NONBLOCK, 0); 74 | if (fd < 0) { 75 | printf("unable to open %s\n", v4l_device); 76 | return; 77 | } 78 | 79 | err = ioctl(fd, VIDIOC_S_OUTPUT, &out); 80 | if (err < 0) { 81 | printf("VIDIOC_S_OUTPUT failed\n"); 82 | close(fd); fd = -1 ; 83 | return; 84 | } 85 | 86 | struct v4l2_crop vcrop ; 87 | memset(&vcrop,0,sizeof(vcrop)); 88 | vcrop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 89 | vcrop.c.top = window.top; 90 | vcrop.c.left = window.left; 91 | vcrop.c.width = window.right-window.left; 92 | vcrop.c.height = window.bottom-window.top; 93 | err = ioctl(fd, VIDIOC_S_CROP, &vcrop); 94 | if (err < 0) { 95 | printf("VIDIOC_S_CROP failed: %u:%u..%ux%u\n",vcrop.c.top,vcrop.c.left,vcrop.c.width,vcrop.c.height); 96 | close(fd); fd = -1 ; 97 | return; 98 | } 99 | 100 | struct v4l2_format fmt ; 101 | memset(&fmt,0,sizeof(fmt)); 102 | fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 103 | 104 | fmt.fmt.pix.field = V4L2_FIELD_ANY; 105 | fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; 106 | fmt.fmt.pix.width = w; 107 | fmt.fmt.pix.height = h; 108 | fmt.fmt.pix.bytesperline = w; 109 | err = ioctl(fd, VIDIOC_S_FMT, &fmt); 110 | if (err < 0) { 111 | printf("VIDIOC_S_FMT failed\n"); 112 | close(fd); fd = -1 ; 113 | return; 114 | } 115 | 116 | err = ioctl(fd, VIDIOC_G_FMT, &fmt); 117 | if (err < 0) { 118 | printf("VIDIOC_G_FMT failed\n"); 119 | close(fd); fd = -1 ; 120 | return; 121 | } 122 | 123 | struct v4l2_requestbuffers reqbuf = {0}; 124 | reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 125 | reqbuf.memory = V4L2_MEMORY_MMAP; 126 | reqbuf.count = nframes; 127 | 128 | err = ioctl(fd, VIDIOC_REQBUFS, &reqbuf); 129 | if ((err == 0) && (reqbuf.count == nframes)) { 130 | bufs = new struct v4l2_buffer [nframes]; 131 | vbufs = new unsigned char *[nframes]; 132 | unsigned i ; 133 | for (i = 0; i < nframes; i++) { 134 | struct v4l2_buffer &buffer = bufs[i]; 135 | buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 136 | buffer.memory = V4L2_MEMORY_MMAP; 137 | buffer.index = i; 138 | 139 | err = ioctl(fd, VIDIOC_QUERYBUF, &buffer); 140 | if (err < 0) { 141 | printf("VIDIOC_QUERYBUF, not enough buffers\n"); 142 | close(fd); fd = -1 ; 143 | return; 144 | } 145 | 146 | vbufs[i] = (unsigned char *) 147 | mmap(NULL, buffer.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buffer.m.offset); 148 | 149 | if (vbufs[i] == (unsigned char *)MAP_FAILED) { 150 | printf("mmap failed\n"); 151 | vbufs[i] = 0 ; 152 | break; 153 | } 154 | memset(vbufs[i],0x80,imgSize()); 155 | bufs_avail |= (1< 266 | #include 267 | #include 268 | #include "tickMs.h" 269 | 270 | static bool volatile die = false ; 271 | 272 | static void ctrlcHandler( int signo ) 273 | { 274 | printf( "\n" ); 275 | die = true ; 276 | } 277 | 278 | int main (int argc, char const * const argv[]) 279 | { 280 | unsigned w = 800 ; 281 | unsigned h = 600 ; 282 | 283 | Rect window = {0}; 284 | if (1 < argc) { 285 | unsigned x,y ; 286 | if (4 == sscanf(argv[1],"%ux%u+%u+%u", &w,&h,&x,&y)) { 287 | window.top = y ; 288 | window.left = x ; 289 | window.right = x+w ; 290 | window.bottom = y+h ; 291 | } else { 292 | fprintf (stderr, "invalid spec: use WxH+x+y\n"); 293 | return -1 ; 294 | } 295 | } else { 296 | window.right = w ; 297 | window.bottom = h ; 298 | } 299 | signal(SIGINT, ctrlcHandler); 300 | while (!die) { 301 | v4l_display_t display(w,h,window,3); 302 | if (display.initialized()) { 303 | printf("display initialized\n" ); 304 | unsigned char i = 128 ; 305 | long long start = tickMs(); 306 | while (i) { 307 | unsigned idx ; 308 | if (display.getBuf(idx)) { 309 | memset(display.getY(idx),i++,display.ySize()); 310 | display.putBuf(idx); 311 | printf("%d", idx); fflush(stdout); 312 | } else { 313 | struct pollfd pfd ; 314 | pfd.fd = display.getFd(); 315 | pfd.events = POLLIN ; 316 | if (0 == poll(&pfd,1,1000)) { 317 | printf("no buffers\n"); 318 | return -1 ; 319 | } 320 | } 321 | } 322 | long long end = tickMs(); 323 | printf("\n"); 324 | unsigned long ms = end-start; 325 | printf("128 frames in %lu ms (%lu fps)\n", ms,(128*1000)/ms); 326 | } else { 327 | printf("error initializing display\n"); 328 | break; 329 | } 330 | } 331 | return 0 ; 332 | } 333 | 334 | #endif 335 | -------------------------------------------------------------------------------- /v4l_display.h: -------------------------------------------------------------------------------- 1 | #ifndef __V4L_DISPLAY_H__ 2 | #define __V4L_DISPLAY_H__ 3 | 4 | #include 5 | #include 6 | extern "C" { 7 | #include 8 | #include 9 | }; 10 | 11 | class v4l_display_t { 12 | public: 13 | v4l_display_t 14 | ( unsigned picWidth, 15 | unsigned picHeight, 16 | Rect const &window, 17 | unsigned numframes ); 18 | ~v4l_display_t (void); 19 | 20 | bool initialized (void) const { return 0 <= fd ; } 21 | unsigned numBufs (void) const { return nframes ; } 22 | 23 | unsigned imgSize(void)const { return ySize()+2*uvSize(); } 24 | unsigned ySize(void) const { return ysize ; } 25 | unsigned yStride(void) const { return ystride ; } 26 | 27 | unsigned uvSize(void) const { return uvsize ; } 28 | unsigned uvStride(void) const { return uvstride ; } 29 | 30 | void pollBufs(void); 31 | 32 | bool getBuf (unsigned &idx); 33 | void putBuf (unsigned idx); 34 | void *getY(unsigned idx) const { return vbufs[idx]; } 35 | void getFrameBuffers( FrameBuffer *&fbs, unsigned &count); 36 | 37 | int getFd (void) const { return fd ; } 38 | private: 39 | v4l_display_t (v4l_display_t const &); // no copies 40 | enum { 41 | MAXFBS = 16 42 | }; 43 | unsigned w ; 44 | unsigned h ; 45 | unsigned ysize ; 46 | unsigned ystride ; 47 | unsigned uvsize ; 48 | unsigned uvstride ; 49 | Rect win ; 50 | unsigned nframes ; 51 | FrameBuffer fbs[MAXFBS]; 52 | int fd ; 53 | struct v4l2_buffer *bufs ; 54 | unsigned char **vbufs ; 55 | unsigned bufs_avail ; 56 | unsigned numQueued ; 57 | bool streaming ; 58 | }; 59 | 60 | #endif 61 | --------------------------------------------------------------------------------