From f829cbff5c8f7aa1ea51da3f9e5a834d24734a22 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 13 Sep 2009 11:13:59 -0300 Subject: Add conexant cx25821 driver From: Palash Bandyopadhyay Add conexant cx25821 driver release v106 of the Athena driver. Priority: normal Signed-off-by: Palash Bandyopadhyay Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/cx25821/audioplayback | 1 + v4l2-apps/util/cx25821/audiorecord | 1 + v4l2-apps/util/cx25821/cx25821-medusa-decoder.c | 106 ++++++++++++ v4l2-apps/util/cx25821/medusaReadWrite.c | 158 +++++++++++++++++ v4l2-apps/util/cx25821/mencode_av | 1 + v4l2-apps/util/cx25821/mencode_video | 1 + v4l2-apps/util/cx25821/mplay_av | 1 + v4l2-apps/util/cx25821/mplay_cifNTSC | 1 + v4l2-apps/util/cx25821/mplay_cifPAL | 1 + v4l2-apps/util/cx25821/mplay_video | 1 + v4l2-apps/util/cx25821/regReadWrite.c | 158 +++++++++++++++++ v4l2-apps/util/cx25821/setAlsaVolume | 2 + v4l2-apps/util/cx25821/setvideosetting.c | 187 ++++++++++++++++++++ v4l2-apps/util/cx25821/upstream_app.c | 221 ++++++++++++++++++++++++ 14 files changed, 840 insertions(+) create mode 100644 v4l2-apps/util/cx25821/audioplayback create mode 100644 v4l2-apps/util/cx25821/audiorecord create mode 100644 v4l2-apps/util/cx25821/cx25821-medusa-decoder.c create mode 100644 v4l2-apps/util/cx25821/medusaReadWrite.c create mode 100644 v4l2-apps/util/cx25821/mencode_av create mode 100644 v4l2-apps/util/cx25821/mencode_video create mode 100644 v4l2-apps/util/cx25821/mplay_av create mode 100644 v4l2-apps/util/cx25821/mplay_cifNTSC create mode 100644 v4l2-apps/util/cx25821/mplay_cifPAL create mode 100644 v4l2-apps/util/cx25821/mplay_video create mode 100644 v4l2-apps/util/cx25821/regReadWrite.c create mode 100644 v4l2-apps/util/cx25821/setAlsaVolume create mode 100644 v4l2-apps/util/cx25821/setvideosetting.c create mode 100644 v4l2-apps/util/cx25821/upstream_app.c (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/cx25821/audioplayback b/v4l2-apps/util/cx25821/audioplayback new file mode 100644 index 000000000..1b09da915 --- /dev/null +++ b/v4l2-apps/util/cx25821/audioplayback @@ -0,0 +1 @@ +aplay -c 2 -r 48000 -f S16_LE $1 diff --git a/v4l2-apps/util/cx25821/audiorecord b/v4l2-apps/util/cx25821/audiorecord new file mode 100644 index 000000000..ee2c46650 --- /dev/null +++ b/v4l2-apps/util/cx25821/audiorecord @@ -0,0 +1 @@ +arecord -D hw:1,0 -d $2 -c 2 -r 48000 -f S16_LE > $1 diff --git a/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c b/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c new file mode 100644 index 000000000..7bd35ed43 --- /dev/null +++ b/v4l2-apps/util/cx25821/cx25821-medusa-decoder.c @@ -0,0 +1,106 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "cx25821.h" + + +// Array for GPIO selected bits for a specific decoder. + +enum GPIO_DEF { DECA_SEL = 0, + DECB_SEL, + DECC_SEL, + DECD_SEL, + MON_SEL = 4}; + +enum GPIO_OCTAL_DEF { OCTAL_DECA_SEL = 0, + OCTAL_DECB_SEL, + OCTAL_DECC_SEL, + OCTAL_DECD_SEL, + OCTAL_DECE_SEL, + OCTAL_DECF_SEL, + OCTAL_DECG_SEL, + OCTAL_DECH_SEL, + OCTAL_MON_SEL = 8 }; + + +// Direction bits are at offset 23:16 +#define Set_GPIO_Direction_Bit_To_OUTPUT(Bit) ((1 << Bit) << 16) + +struct medusa_decoder { + int _cur_dec; + unsigned short _num_vdec; +}; + +//////////////////////////////////////////////////////////////////////////////////////// +// Selects Medusa Decoder Channel. +//////////////////////////////////////////////////////////////////////////////////////// +void medusa_decoder_select(struct cx25821_dev *dev, struct medusa_decoder *dec, int decoder) +{ + + if (decoder < DECA_SEL && decoder > MON_SEL ) + return; + + dec->_cur_dec = decoder; + + u32 gpioRegister = cx_read(GP0_IO); + u32 value = (gpioRegister & 0xFFFFFFF0) | dec->_cur_dec; + cx_write( GP0_IO, value ); +} + +//////////////////////////////////////////////////////////////////////////////////////// +// Sets the GPIO pin directions +// Parameters: +// +//////////////////////////////////////////////////////////////////////////////////////// +void medusa_video_set_gpiopin_directions_to_output(struct cx25821_dev *dev, struct medusa_decoder *dec ) +{ + // Here we will make sure that the GPIOs 0-3 are output. keep the rest as is + u32 gpioRegister = cx_read( GP0_IO ); + + // This operation will set the GPIO bits below. + if (dec->_num_vdec == 4) + { + cx_write( GP0_IO, + gpioRegister + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECA_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECB_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECC_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(DECD_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(MON_SEL)) ); + medusa_decoder_select(dev, dec, MON_SEL); + } + else + { + cx_write( GP0_IO, + gpioRegister + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECA_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECB_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECC_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECD_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECE_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECF_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECG_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_DECH_SEL)) + | (Set_GPIO_Direction_Bit_To_OUTPUT(OCTAL_MON_SEL)) ); + medusa_decoder_select(dev, dec, OCTAL_MON_SEL); + } +} diff --git a/v4l2-apps/util/cx25821/medusaReadWrite.c b/v4l2-apps/util/cx25821/medusaReadWrite.c new file mode 100644 index 000000000..cf4a1a5e6 --- /dev/null +++ b/v4l2-apps/util/cx25821/medusaReadWrite.c @@ -0,0 +1,158 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define MEDUSA_READ 910 +#define MEDUSA_WRITE 911 + +typedef struct{ + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; +}downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./medusa d 1 r 0x01\n"); + printf("Sample Usage: ./medusa d 1 w 0x0 0x2\n"); + printf(" d device_id Device ID (1 and above) for MultiCard\n"); + printf(" r Read Medusa register\n"); + printf(" w Write Medusa register\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + + int register_addr = 0; + int write_value = 0; + + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 5 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 'r': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + + arguments.reg_address = register_addr; + arguments.command = MEDUSA_READ; + + printf("Read parameters: read register = 0x%x, command = %d \n", arguments.reg_address, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + printf("Reg 0x%x = 0x%x\n", arguments.reg_address, arguments.reg_data); + } + break; + + case 'w': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + sscanf(argv[i+2], "%x", &write_value ); + i++; + + arguments.command = MEDUSA_WRITE; + arguments.reg_address = register_addr; + arguments.reg_data = write_value; + + printf("Write parameters: write register = 0x%x, write_value = 0x%x, command = %d \n", arguments.reg_address, arguments.reg_data, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} + diff --git a/v4l2-apps/util/cx25821/mencode_av b/v4l2-apps/util/cx25821/mencode_av new file mode 100644 index 000000000..6533cb4d8 --- /dev/null +++ b/v4l2-apps/util/cx25821/mencode_av @@ -0,0 +1 @@ +mencoder tv:// -tv driver=v4l2:input=0:norm=ntsc:width=720:height=480:outfmt=yuy2:device=/dev/video$1:forceaudio:alsa=1:adevice=hw.1:audiorate=48000:immediatemode=0:amode=1 buffersize=64 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=5000:keyint=30 -oac mp3lame -lameopts br=128:cbr:mode=3 -ffourcc divx -o $2 \ No newline at end of file diff --git a/v4l2-apps/util/cx25821/mencode_video b/v4l2-apps/util/cx25821/mencode_video new file mode 100644 index 000000000..9f0c29ebd --- /dev/null +++ b/v4l2-apps/util/cx25821/mencode_video @@ -0,0 +1 @@ +mencoder tv:// -tv driver=v4l2:input=0:norm=ntsc:width=720:height=480:outfmt=yuy2:device=/dev/video$1 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=5000:keyint=30 -nosound -ffourcc divx -o $2 diff --git a/v4l2-apps/util/cx25821/mplay_av b/v4l2-apps/util/cx25821/mplay_av new file mode 100644 index 000000000..0b11e7af6 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_av @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=720:height=480:outfmt=yuy2:alsa=1:adevice=hw.1:audiorate=48000:immediatemode=0:amode=1 tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_cifNTSC b/v4l2-apps/util/cx25821/mplay_cifNTSC new file mode 100644 index 000000000..ba3c34ec2 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_cifNTSC @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=320:height=240:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_cifPAL b/v4l2-apps/util/cx25821/mplay_cifPAL new file mode 100644 index 000000000..2139ffb0a --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_cifPAL @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=PAL-BG:width=352:height=288:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/mplay_video b/v4l2-apps/util/cx25821/mplay_video new file mode 100644 index 000000000..7d9567662 --- /dev/null +++ b/v4l2-apps/util/cx25821/mplay_video @@ -0,0 +1 @@ +mplayer -vo x11 -tv driver=v4l2:device=/dev/video$1:input=1:norm=NTSC-M:width=720:height=480:outfmt=yuy2: tv:///0 diff --git a/v4l2-apps/util/cx25821/regReadWrite.c b/v4l2-apps/util/cx25821/regReadWrite.c new file mode 100644 index 000000000..2d506183d --- /dev/null +++ b/v4l2-apps/util/cx25821/regReadWrite.c @@ -0,0 +1,158 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define REG_READ 900 +#define REG_WRITE 901 + +typedef struct{ + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; + int reg_address; + int reg_data; +}downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./reg d 1 r 0x01\n"); + printf("Sample Usage: ./reg d 1 w 0x0 0x2\n"); + printf(" d device_id Device ID (1 and above) for MultiCard\n"); + printf(" r Read Athena register\n"); + printf(" w Write Athena register\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + + int register_addr = 0; + int write_value = 0; + + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 5 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 'r': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + + arguments.reg_address = register_addr; + arguments.command = REG_READ; + + printf("Read parameters: read register = 0x%x, command = %d \n", arguments.reg_address, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + printf("Reg 0x%x = 0x%x\n", arguments.reg_address, arguments.reg_data); + } + break; + + case 'w': + { + downstream_user_struct arguments; + + sscanf(param_temp, "%x", ®ister_addr ); + sscanf(argv[i+2], "%x", &write_value ); + i++; + + arguments.command = REG_WRITE; + arguments.reg_address = register_addr; + arguments.reg_data = write_value; + + printf("Write parameters: write register = 0x%x, write_value = 0x%x, command = %d \n", arguments.reg_address, arguments.reg_data, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} + diff --git a/v4l2-apps/util/cx25821/setAlsaVolume b/v4l2-apps/util/cx25821/setAlsaVolume new file mode 100644 index 000000000..55dd3dc89 --- /dev/null +++ b/v4l2-apps/util/cx25821/setAlsaVolume @@ -0,0 +1,2 @@ +amixer set Master,0 100% unmute +amixer set Capture,0 90% captur diff --git a/v4l2-apps/util/cx25821/setvideosetting.c b/v4l2-apps/util/cx25821/setvideosetting.c new file mode 100644 index 000000000..87e36045d --- /dev/null +++ b/v4l2-apps/util/cx25821/setvideosetting.c @@ -0,0 +1,187 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + + +#define SET_VIDEO_STD 800 +#define SET_PIXEL_FORMAT 1000 +#define ENABLE_CIF_RESOLUTION 1001 + + +#define PIXEL_FRMT_422 4 +#define PIXEL_FRMT_411 5 +#define PIXEL_FRMT_Y8 6 +#define ALL_DECODERS 752 + +typedef struct { + char *vid_stdname; + int pixel_format; + int cif_resolution_enable; + int cif_width; + int decoder_select; + int command; +} downstream_user_struct; + + +void print_usage() +{ + printf("\n*********************************\n"); + printf("Sample Usage: ./set d 1 standard NTSC format 422 7 resolution 320 7\n"); + printf(" device_id Device ID (1 and above) for MultiCard\n"); + printf(" standard Video Standard (PAL/NTSC)\n"); + printf(" format Output Pixel Format (422 or 411) for specific decoder (e.g. 7)\n"); + printf(" resolution 352/320 for CIF and 720 for D1 resolution for specific decoder (e.g. 7)\n"); +} + +int main(int argc, char** argv) +{ + unsigned int cmd= 0 ; + int fp; + int i = 1, j = 0, k = 0, len = 0; + int mode = 0; + int pixel_format = 0; + int width_input = 0; + int decoder_input = 0; + int device_id = 0, video_id = 11; + char * temp2; + char *device_str[4] = {"/dev/video11", "/dev/video23", "/dev/video35", "/dev/video47"}; + + char mode_temp = 's'; + char *param_temp; + + + if(argc < 3 || (tolower(*(argv[1])) != 'd') ) + { + print_usage(); + return -EINVAL; + } + + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_usage(); + return -EINVAL; + } + + printf("\n********************************* \n"); + + if((fp = open(device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", device_str[device_id-1]); + + + for( ; i < argc; i++) + { + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + param_temp = argv[i+1]; + + + switch(mode_temp) + { + case 's': + { + downstream_user_struct arguments; + char * temp = param_temp; + arguments.vid_stdname = (tolower(temp[0]) == 'p') ? "PAL" : "NTSC"; + arguments.command = SET_VIDEO_STD; + + printf("User parameters: vid_stdname = %s, command = %d \n", arguments.vid_stdname, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + case 'f': + { + sscanf(param_temp, "%d", &pixel_format ); + sscanf(argv[i+2], "%d", &decoder_input ); i++; + + if( pixel_format < 411 || pixel_format > 422) + pixel_format = 422; + + if( decoder_input < 0 ) + decoder_input = ALL_DECODERS; + + downstream_user_struct arguments; + arguments.pixel_format = (pixel_format == 411) ? PIXEL_FRMT_411 : PIXEL_FRMT_422; + arguments.decoder_select = decoder_input; + arguments.command = SET_PIXEL_FORMAT; + + printf("User parameters: pixel_format = %d, decoder_input = %d, command = %d \n", arguments.pixel_format, arguments.decoder_select, arguments.command); + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + case 'r': + { + sscanf(param_temp, "%d", &width_input ); + sscanf(argv[i+2], "%d", &decoder_input ); i++; + + if( width_input < 320 || width_input > 352 ) + width_input = 720; + + if( decoder_input < 0 ) + decoder_input = ALL_DECODERS; + + downstream_user_struct arguments; + arguments.cif_resolution_enable = (width_input == 320 || width_input == 352) ? 1 : 0; + arguments.cif_width = width_input; + arguments.decoder_select = decoder_input; + arguments.command = ENABLE_CIF_RESOLUTION; + + printf("User parameters: cif_resolution_enable = %d, decoder_input = %d, command = %d \n", arguments.cif_resolution_enable, arguments.decoder_select, arguments.command); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("Please verify the options are correct!\n"); + break; + } + + i++; + } + + + printf("********************************* \n\n"); + close(fp); + return 0; +} diff --git a/v4l2-apps/util/cx25821/upstream_app.c b/v4l2-apps/util/cx25821/upstream_app.c new file mode 100644 index 000000000..97f7b84aa --- /dev/null +++ b/v4l2-apps/util/cx25821/upstream_app.c @@ -0,0 +1,221 @@ +/* + * Driver for the Conexant CX25821 PCIe bridge + * + * Copyright (C) 2009 Conexant Systems Inc. + * Authors , + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include + +#define VID_UPSTREAM_SRAM_CHANNEL_I 9 +#define VID_UPSTREAM_SRAM_CHANNEL_J 10 +#define AUDIO_UPSTREAM_SRAM_CHANNEL_B 11 +#define PIXEL_FRMT_422 4 +#define PIXEL_FRMT_411 5 +#define UPSTREAM_START_VIDEO 700 +#define UPSTREAM_STOP_VIDEO 701 +#define UPSTREAM_START_AUDIO 702 +#define UPSTREAM_STOP_AUDIO 703 +#define UPSTREAM_DUMP_REGISTERS 702 + + +typedef struct { + char *input_filename; + char *vid_stdname; + int pixel_format; + int channel_select; + int command; +} upstream_user_struct; + +void print_video_usage() +{ + printf("\n************************************************************************ \n"); + printf("Video Sample Usage: ./upstream_app d 1 v /root/filename.yuv NTSC 422 1 start \n"); + printf("Argument 0: ./upstream_app \n"); + printf("Argument 1: Device ID (1 and above)\n"); + printf("Argument 2: v for video\n"); + printf("Argument 3: input file name \n"); + printf("Argument 4: Video Standard \n"); + printf("Argument 5: Pixel Format (Y422 or Y411) \n"); + printf("Argument 6: Upstream Channel Number\n"); + printf("Argument 7: start/stop command\n\n"); +} + +void print_audio_usage() +{ + printf("\n************************************************************************ \n"); + printf("Audio Sample Usage: ./upstream_app d 1 a /root/audio.wav start\n"); + printf("Argument 0: ./upstream_app \n"); + printf("Argument 1: Device ID (1 and above)\n"); + printf("Argument 2: a for audio \n"); + printf("Argument 3: input file name \n"); + printf("Argument 4: start/stop command\n\n"); +} + +int main(int argc, char** argv) +{ + int fp; + unsigned int cmd= 0 ; + int i = 1; + int mode = 0; + int pixel_format = 422; + int channel_select = 1; + int device_id = 0, video_id = 11; + char * temp2; + char *video_device_str[4][2] = {{"/dev/video8", "/dev/video9"}, {"/dev/video20", "/dev/video21"}, + {"/dev/video32", "/dev/video33"}, {"/dev/video44", "/dev/video45"} }; + char *audio_device_str[4] = {"/dev/video10", "/dev/video22", "/dev/video34", "/dev/video46"}; + char mode_temp = 'v'; + + if(argc < 2 || (tolower(*(argv[1])) != 'd') ) + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + else + { + sscanf(argv[2], "%d", &device_id ); + i += 2; + + if( device_id <= 0 || device_id > 4 ) + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + + temp2 = argv[i]; + mode_temp = tolower(temp2[0]); + switch(mode_temp) + { + case 'v': + if( argc < 9 ) + { + print_video_usage(); + return -EINVAL; + } + break; + + case 'a': + if( argc < 6 ) + { + print_audio_usage(); + return -EINVAL; + } + break; + } + } + + if( mode_temp == 'v' || mode_temp == 'a' ) + { + FILE* file_ptr = fopen(argv[4], "r"); + + if( !file_ptr ) + { + printf("\nERROR: %s file does NOT exist!!! \n\n", argv[4]); + return -EINVAL; + } + + fclose(file_ptr); + } + else + { + print_video_usage(); + print_audio_usage(); + return -EINVAL; + } + + printf("\n*************************************************************** \n"); + + switch(mode_temp) + { + case 'v': + { + char * temp = argv[5]; + upstream_user_struct arguments; + arguments.input_filename = argv[4]; + arguments.vid_stdname = (tolower(temp[0]) == 'p') ? "PAL" : "NTSC"; + sscanf(argv[6], "%d", &pixel_format); + sscanf(argv[7], "%d", &channel_select); + arguments.pixel_format = (pixel_format == 422) ? PIXEL_FRMT_422 : PIXEL_FRMT_411; + arguments.channel_select = (channel_select==1) ? VID_UPSTREAM_SRAM_CHANNEL_I : VID_UPSTREAM_SRAM_CHANNEL_J; + temp = argv[8]; + arguments.command = (strcasecmp("STOP", temp) == 0) ? UPSTREAM_STOP_VIDEO : UPSTREAM_START_VIDEO; + + + if( channel_select >= 1 && channel_select <= 2 ) + { + if((fp = open(video_device_str[device_id-1][channel_select-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", video_device_str[device_id-1][channel_select-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", video_device_str[device_id-1][channel_select-1]); + printf("UPSTREAM parameters: filename = %s, channel_select(I=1) = %d \n", arguments.input_filename, channel_select); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + { + printf("Error: ioctl FAILED!\n"); + } + } + } + break; + + case 'a': + { + char * temp = argv[5]; + upstream_user_struct arguments; + arguments.input_filename = argv[4]; + arguments.vid_stdname = "NTSC"; + arguments.pixel_format = PIXEL_FRMT_422; + arguments.channel_select = AUDIO_UPSTREAM_SRAM_CHANNEL_B; + arguments.command = (strcasecmp("STOP", temp) == 0) ? UPSTREAM_STOP_AUDIO : UPSTREAM_START_AUDIO; + + + if((fp = open(audio_device_str[device_id-1], O_RDWR)) == -1) + { + printf("Error: cannot open device file %s !\n", audio_device_str[device_id-1]); + return -EINVAL; + } + + printf("Device %s open for IOCTL successfully!\n", audio_device_str[device_id-1]); + printf("UPSTREAM parameters: filename = %s, audio channel = %d \n", arguments.input_filename, arguments.channel_select); + + + if((ioctl(fp, arguments.command, (char *) &arguments)) == -1) + printf("Error: ioctl FAILED!\n"); + } + break; + + default: + printf("ERROR: INVALID ioctl command!\n"); + return -EINVAL; + } + + printf("*************************************************************** \n\n"); + close(fp); + return 0; +} -- cgit v1.2.3 From a6abaa333259a9d636720762d2aef33727eaf602 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 14 Sep 2009 09:49:16 -0300 Subject: Start userspace decoding application for tm6000 From: Mauro Carvalho Chehab This small application allows testing tm6000 raw format decoding in software. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/Makefile | 8 +- v4l2-apps/util/decode_tm6000.c | 225 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 v4l2-apps/util/decode_tm6000.c (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index 29f3f4852..0bee48571 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -28,7 +28,7 @@ endif CPPFLAGS += -I../include -D_GNU_SOURCE LDFLAGS += -lm -binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl v4l2-sysfs-path +binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl v4l2-sysfs-path decode_tm6000 ifeq ($(prefix),) prefix = /usr @@ -53,6 +53,12 @@ qv4l2: v4l2-dbg: v4l2-dbg.o v4l2-chipids.o $(CXX) $^ -o $@ +../lib/libv4l2.a: ../lib/v4l2_driver.c ../lib/frequencies.c + make -C ../lib libv4l2.a + +decode_tm6000: decode_tm6000.o ../lib/libv4l2.a + + v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h v4l2-sysfs-path.o: v4l2-sysfs-path.c ../libv4l2util/v4l2_driver.h diff --git a/v4l2-apps/util/decode_tm6000.c b/v4l2-apps/util/decode_tm6000.c new file mode 100644 index 000000000..7ca88e78e --- /dev/null +++ b/v4l2-apps/util/decode_tm6000.c @@ -0,0 +1,225 @@ +/* + decode_tm6000.c - decode multiplexed format from TM5600/TM6000 USB + + Copyright (C) 2007 Mauro Carvalho Chehab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "../lib/v4l2_driver.h" +#include +#include +#include + +const char *argp_program_version="decode_tm6000 version 0.0.1"; +const char *argp_program_bug_address="Mauro Carvalho Chehab "; +const char doc[]="Decodes tm6000 proprietary format streams"; +const struct argp_option options[] = { + {"verbose", 'v', 0, 0, "enables debug messages", 0}, + {"device", 'd', "DEV", 0, "uses device for reading", 0}, + {"output", 'o', "FILE", 0, "outputs raw stream to a file", 0}, + {"input", 'i', "FILE", 0, "parses a file, instead of a device", 0}, + {"audio", 'a', 0, 0, "outputs audio on stdout", 0}, + { 0, 0, 0, 0, 0, 0 } +}; + +static int debug=0, audio=0; +static char *devname="/dev/video0"; +static char *filename=NULL; +static enum { + NORMAL, + INPUT, + OUTPUT +} mode = NORMAL; + +//const char args_doc[]="ARG1 ARG2"; + +static error_t parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) { + case 'a': + audio++; + break; + case 'v': + debug++; + break; + case 'd': + devname=arg; + break; + case 'i': + case 'o': + if (mode!=NORMAL) { + argp_error(state,"You can't use input/output options simultaneously.\n"); + break; + } + if (key=='i') + mode=INPUT; + else + mode=OUTPUT; + + filename=arg; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { + .options=options, + .parser=parse_opt, + .args_doc=NULL, + .doc=doc, +}; + +#define TM6000_URB_MSG_LEN 180 +enum { + TM6000_URB_MSG_VIDEO=1, + TM6000_URB_MSG_AUDIO, + TM6000_URB_MSG_VBI, + TM6000_URB_MSG_PTS, + TM6000_URB_MSG_ERR, +}; + +const char *tm6000_msg_type[]= { + "unknown(0)", //0 + "video", //1 + "audio", //2 + "vbi", //3 + "pts", //4 + "err", //5 + "unknown(6)", //6 + "unknown(7)", //7 +}; + +#define dprintf(fmt,arg...) \ + if (debug) fprintf(stderr, fmt, ##arg) + +int main (int argc, char*argv[]) +{ + FILE *fp; + unsigned char c, buf[TM6000_URB_MSG_LEN], img[720*2*480]; + unsigned int cmd, cpysize, pktsize, size, field, block, line, pos=0; + unsigned long header=0; + int linesize=720*2,skip=0; + struct v4l2_format fmt; + struct v4l2_driver drv; + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (mode!=INPUT) { + if (v4l2_open (devname, 1,&drv)<0) { + perror ("Error opening dev"); + return -1; + } + fp=fdopen(drv.fd,"r"); + if (!fp) { + perror("error associating dev"); + return -1; + } + + memset (&fmt,0,sizeof(fmt)); + + uint32_t pixelformat=V4L2_PIX_FMT_TM6000; + + if (v4l2_gettryset_fmt_cap (&drv,V4L2_SET,&fmt, 720, 480, + pixelformat,V4L2_FIELD_ANY)) { + perror("set_input to tm6000 raw format"); + return -1; + } + } + + if (mode==INPUT) { + fp=fopen(filename,"r"); + if (!fp) { + perror ("error opening a file for parsing"); + return -1; + } + dprintf("file %s opened for parsing\n",filename); + } + + if (mode==OUTPUT) { + char outbuf[2<<18]; + FILE *fout; + + fout=fopen(filename,"w"); + if (!fout) { + perror ("error opening a file to write"); + return -1; + } + dprintf("file %s opened for output\n",filename); + do { + size=fread(outbuf,1, sizeof(outbuf), fp); + if (!size) { + fclose (fp); + return 0; + } + dprintf("writing %d bytes\n",size); + fwrite(outbuf,1, size,fout); +// fflush(fout); + } while (1); + } + + while (1) { + skip=0; + header=0; + do { + c=fgetc(fp); + header=(header>>8)&0xffffff; + header=header|(c<<24); + skip++; + } while ( (((header>>24)&0xff) != 0x47) ); + + /* split the header fields */ + size = (((header & 0x7e)<<1) -1) * 4; + block = (header>>7) & 0xf; + field = (header>>11) & 0x1; + line = (header>>12) & 0x1ff; + cmd = (header>>21) & 0x7; + + /* Read the remaining buffer */ + fread((char *)buf,sizeof(buf), 1, fp); + + /* FIXME: Mounts the image as field0+field1 + * It should, instead, check if the user selected + * entrelaced or non-entrelaced mode + */ + pos=((line<<1)+field)*linesize+ + block*TM6000_URB_MSG_LEN; + + /* Prints debug info */ + dprintf("0x%08x (skip %d), %s size=%d, num=%d,line=%d, field=%d\n", + (unsigned int)header, skip, + tm6000_msg_type[cmd], + size, block, line, field); + + /* Don't allow to write out of the buffer */ + if (pos+sizeof(buf) > sizeof(img)) + cmd = TM6000_URB_MSG_ERR; + + /* handles each different URB message */ + switch(cmd) { + case TM6000_URB_MSG_VIDEO: + /* Fills video buffer */ + memcpy(buf,&img[pos],sizeof(buf)); + case TM6000_URB_MSG_AUDIO: + if (audio) + fwrite(buf,sizeof(buf),1,stdout); +// case TM6000_URB_MSG_VBI: +// case TM6000_URB_MSG_PTS: + break; + } + } + fclose(fp); + return 0; +} -- cgit v1.2.3 From 296eff5876443f5e922bcaf61974bc9c2b2d6271 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 21 Aug 2007 17:33:10 -0300 Subject: tm6000: Add support for mmap From: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/util/decode_tm6000.c | 70 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 2 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/decode_tm6000.c b/v4l2-apps/util/decode_tm6000.c index 7ca88e78e..77920a593 100644 --- a/v4l2-apps/util/decode_tm6000.c +++ b/v4l2-apps/util/decode_tm6000.c @@ -20,6 +20,7 @@ #include #include #include +#include const char *argp_program_version="decode_tm6000 version 0.0.1"; const char *argp_program_bug_address="Mauro Carvalho Chehab "; @@ -30,10 +31,11 @@ const struct argp_option options[] = { {"output", 'o', "FILE", 0, "outputs raw stream to a file", 0}, {"input", 'i', "FILE", 0, "parses a file, instead of a device", 0}, {"audio", 'a', 0, 0, "outputs audio on stdout", 0}, + {"read", 'r', 0, 0, "use read() instead of mmap method", 0}, { 0, 0, 0, 0, 0, 0 } }; -static int debug=0, audio=0; +static int debug=0, audio=0, use_mmap=1; static char *devname="/dev/video0"; static char *filename=NULL; static enum { @@ -42,6 +44,8 @@ static enum { OUTPUT } mode = NORMAL; +static FILE *fout; + //const char args_doc[]="ARG1 ARG2"; static error_t parse_opt (int key, char *arg, struct argp_state *state) @@ -50,6 +54,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) case 'a': audio++; break; + case 'r': + use_mmap=0; + break; case 'v': debug++; break; @@ -105,6 +112,61 @@ const char *tm6000_msg_type[]= { #define dprintf(fmt,arg...) \ if (debug) fprintf(stderr, fmt, ##arg) +int recebe_buffer (struct v4l2_buffer *v4l2_buf, struct v4l2_t_buf *buf) +{ + fwrite (buf->start,buf->length,1,fout); + return 0; +} + + +int read_mmap(struct v4l2_driver *drv) +{ + double freq; + + freq=193.25 * 1000 * 1000; + v4l2_getset_freq (drv,V4L2_SET, &freq); + + printf("Preparing for frames...\n"); + fflush (stdout); + sleep(1); + + v4l2_mmap_bufs(drv, 2); + + v4l2_start_streaming(drv); + + printf("Waiting for frames...\n"); + while (1) { + fd_set fds; + struct timeval tv; + int r; + + FD_ZERO (&fds); + FD_SET (drv->fd, &fds); + + /* Timeout. */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + r = select (drv->fd + 1, &fds, NULL, NULL, &tv); + if (-1 == r) { + if (EINTR == errno) + + perror ("select"); + return errno; + } + + if (0 == r) { + fprintf (stderr, "select timeout\n"); + return errno; + } + + if (v4l2_rcvbuf(drv, recebe_buffer)) + break; + } + return 0; +} + + int main (int argc, char*argv[]) { FILE *fp; @@ -150,7 +212,6 @@ int main (int argc, char*argv[]) if (mode==OUTPUT) { char outbuf[2<<18]; - FILE *fout; fout=fopen(filename,"w"); if (!fout) { @@ -158,6 +219,11 @@ int main (int argc, char*argv[]) return -1; } dprintf("file %s opened for output\n",filename); + + if (use_mmap) { + return (read_mmap(&drv)); + } + do { size=fread(outbuf,1, sizeof(outbuf), fp); if (!size) { -- cgit v1.2.3 From 1f46467cd4eae4c11e8f91554679f10ac8b2da53 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 14 Sep 2009 10:08:44 -0300 Subject: Improve decode_tm6000 for better usage of mmap method From: Mauro Carvalho Chehab Now, mmap method is the default, when reading from tm6000 V4L2 device. Also, now, it is possible to specify the channel frequency via command line, and the number of video buffers to be used. Priority: normal Signed-off-by: Mauro Carvalho Chehab --- v4l2-apps/libv4l2util/v4l2_driver.c | 12 ++- v4l2-apps/util/decode_tm6000.c | 195 +++++++++++++++++++++++++----------- 2 files changed, 141 insertions(+), 66 deletions(-) (limited to 'v4l2-apps') diff --git a/v4l2-apps/libv4l2util/v4l2_driver.c b/v4l2-apps/libv4l2util/v4l2_driver.c index 94f826968..919119b6a 100644 --- a/v4l2-apps/libv4l2util/v4l2_driver.c +++ b/v4l2-apps/libv4l2util/v4l2_driver.c @@ -646,6 +646,9 @@ int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) return 0; } +/* Returns <0, if error, 0 if nothing to read and , if something + read + */ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) { int ret; @@ -668,7 +671,7 @@ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) default: perror ("dqbuf"); - return errno; + return -errno; } } prt_buf_info("DQBUF",&buf); @@ -677,19 +680,18 @@ int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) ret = rec_buf (&buf,&drv->bufs[buf.index]); - if (ret) { + if (ret<0) { v4l2_free_bufs(drv); return ret; } if (-1 == xioctl (drv->fd, VIDIOC_QBUF, &buf)) { perror ("qbuf"); - return errno; + return -errno; } - return 0; + return ret; } - int v4l2_start_streaming(struct v4l2_driver *drv) { uint32_t i; diff --git a/v4l2-apps/util/decode_tm6000.c b/v4l2-apps/util/decode_tm6000.c index 77920a593..d622360d2 100644 --- a/v4l2-apps/util/decode_tm6000.c +++ b/v4l2-apps/util/decode_tm6000.c @@ -21,6 +21,10 @@ #include #include #include +#include +#include +#include +#include const char *argp_program_version="decode_tm6000 version 0.0.1"; const char *argp_program_bug_address="Mauro Carvalho Chehab "; @@ -30,12 +34,16 @@ const struct argp_option options[] = { {"device", 'd', "DEV", 0, "uses device for reading", 0}, {"output", 'o', "FILE", 0, "outputs raw stream to a file", 0}, {"input", 'i', "FILE", 0, "parses a file, instead of a device", 0}, + {"freq", 'f', "Freq", 0, "station frequency, in MHz (default is 193.25)", 0}, + {"nbufs", 'n', "quant",0, "number of video buffers", 0}, {"audio", 'a', 0, 0, "outputs audio on stdout", 0}, {"read", 'r', 0, 0, "use read() instead of mmap method", 0}, { 0, 0, 0, 0, 0, 0 } }; -static int debug=0, audio=0, use_mmap=1; +static char outbuf[692224]; +static int debug=0, audio=0, use_mmap=1, nbufs=4; +static float freq_mhz=193.25; static char *devname="/dev/video0"; static char *filename=NULL; static enum { @@ -76,6 +84,14 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) filename=arg; break; + case 'f': + freq_mhz=atof(arg); + break; + case 'n': + nbufs=atoi(arg); + if (nbufs<2) + nbufs=2; + break; default: return ARGP_ERR_UNKNOWN; } @@ -114,105 +130,150 @@ const char *tm6000_msg_type[]= { int recebe_buffer (struct v4l2_buffer *v4l2_buf, struct v4l2_t_buf *buf) { - fwrite (buf->start,buf->length,1,fout); - return 0; + dprintf("Received %d bytes\n",buf->length); +fflush(stdout); + memcpy (outbuf,buf->start,buf->length); + return buf->length; } -int read_mmap(struct v4l2_driver *drv) +int prepare_read (struct v4l2_driver *drv) { + struct v4l2_format fmt; double freq; + int rc; + + memset (drv,0,sizeof(*drv)); + + if (v4l2_open (devname, 1,drv)<0) { + perror ("Error opening dev"); + return -1; + } - freq=193.25 * 1000 * 1000; - v4l2_getset_freq (drv,V4L2_SET, &freq); + memset (&fmt,0,sizeof(fmt)); - printf("Preparing for frames...\n"); - fflush (stdout); - sleep(1); + uint32_t pixelformat=V4L2_PIX_FMT_TM6000; - v4l2_mmap_bufs(drv, 2); + if (v4l2_gettryset_fmt_cap (drv,V4L2_SET,&fmt, 720, 480, + pixelformat,V4L2_FIELD_ANY)) { + perror("set_input to tm6000 raw format"); + return -1; + } + + if (freq_mhz) { + freq=freq_mhz * 1000 * 1000; + rc=v4l2_getset_freq (drv,V4L2_SET, &freq); + if (rc<0) + printf ("Cannot set freq to %.3f MHz\n",freq_mhz); + } - v4l2_start_streaming(drv); + if (use_mmap) { + printf("Preparing for receiving frames on %d buffers...\n",nbufs); + fflush (stdout); + rc=v4l2_mmap_bufs(drv, nbufs); + if (rc<0) { + printf ("Cannot mmap %d buffers\n",nbufs); + return -1; + } + +// v4l2_stop_streaming(&drv); + rc=v4l2_start_streaming(drv); + if (rc<0) { + printf ("Cannot start streaming\n"); + return -1; + } + } printf("Waiting for frames...\n"); - while (1) { + + return 0; +} + +int read_stream (struct v4l2_driver *drv, int fd) +{ + if (use_mmap) { fd_set fds; struct timeval tv; int r; FD_ZERO (&fds); - FD_SET (drv->fd, &fds); + FD_SET (fd, &fds); /* Timeout. */ tv.tv_sec = 2; tv.tv_usec = 0; - r = select (drv->fd + 1, &fds, NULL, NULL, &tv); + r = select (fd + 1, &fds, NULL, NULL, &tv); if (-1 == r) { - if (EINTR == errno) - - perror ("select"); - return errno; + if (EINTR == errno) { + perror ("select"); + return -errno; + } } if (0 == r) { fprintf (stderr, "select timeout\n"); - return errno; + return -errno; } - if (v4l2_rcvbuf(drv, recebe_buffer)) - break; + return v4l2_rcvbuf(drv, recebe_buffer); + } else { + int size=read(fd, outbuf, sizeof(outbuf)); + return size; } + return 0; } +int read_char (struct v4l2_driver *drv, int fd) +{ + static int sizebuf=0; + static unsigned char *p=NULL; + unsigned char c; + + if (sizebuf<=0) { + sizebuf=read_stream(drv,fd); + if (sizebuf<=0) + return -1; + p=(unsigned char *)outbuf; + } + c=*p; + p++; + sizebuf--; + + return c; +} + int main (int argc, char*argv[]) { - FILE *fp; - unsigned char c, buf[TM6000_URB_MSG_LEN], img[720*2*480]; + int fd; + unsigned int i; + unsigned char buf[TM6000_URB_MSG_LEN], img[720*2*480]; unsigned int cmd, cpysize, pktsize, size, field, block, line, pos=0; unsigned long header=0; int linesize=720*2,skip=0; - struct v4l2_format fmt; struct v4l2_driver drv; argp_parse (&argp, argc, argv, 0, 0, 0); if (mode!=INPUT) { - if (v4l2_open (devname, 1,&drv)<0) { - perror ("Error opening dev"); - return -1; - } - fp=fdopen(drv.fd,"r"); - if (!fp) { - perror("error associating dev"); - return -1; - } - - memset (&fmt,0,sizeof(fmt)); - - uint32_t pixelformat=V4L2_PIX_FMT_TM6000; - - if (v4l2_gettryset_fmt_cap (&drv,V4L2_SET,&fmt, 720, 480, - pixelformat,V4L2_FIELD_ANY)) { - perror("set_input to tm6000 raw format"); + if (prepare_read (&drv)<0) return -1; - } - } + fd=drv.fd; + } else { + /*mode == INPUT */ - if (mode==INPUT) { - fp=fopen(filename,"r"); - if (!fp) { + fd=open(filename,O_RDONLY); + if (fd<0) { perror ("error opening a file for parsing"); return -1; } dprintf("file %s opened for parsing\n",filename); + use_mmap=0; } if (mode==OUTPUT) { - char outbuf[2<<18]; - fout=fopen(filename,"w"); if (!fout) { perror ("error opening a file to write"); @@ -220,15 +281,12 @@ int main (int argc, char*argv[]) } dprintf("file %s opened for output\n",filename); - if (use_mmap) { - return (read_mmap(&drv)); - } - do { - size=fread(outbuf,1, sizeof(outbuf), fp); - if (!size) { - fclose (fp); - return 0; + size=read_stream (&drv,fd); + + if (size<=0) { + close (fd); + return -1; } dprintf("writing %d bytes\n",size); fwrite(outbuf,1, size,fout); @@ -236,11 +294,18 @@ int main (int argc, char*argv[]) } while (1); } + while (1) { skip=0; header=0; do { - c=fgetc(fp); + int c; + c=read_char (&drv,fd); + if (c<0) { + perror("read"); + return -1; + } + header=(header>>8)&0xffffff; header=header|(c<<24); skip++; @@ -254,7 +319,15 @@ int main (int argc, char*argv[]) cmd = (header>>21) & 0x7; /* Read the remaining buffer */ - fread((char *)buf,sizeof(buf), 1, fp); + for (i=0;i sizeof(img)) @@ -286,6 +359,6 @@ int main (int argc, char*argv[]) break; } } - fclose(fp); + close(fd); return 0; } -- cgit v1.2.3