Staging: easycap: add easycap driver
This adds the easycap USB video adapter driver to the staging directory. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
178f16db8f
Коммит
702422bd2d
|
@ -149,5 +149,7 @@ source "drivers/staging/mrst-touchscreen/Kconfig"
|
|||
|
||||
source "drivers/staging/msm/Kconfig"
|
||||
|
||||
source "drivers/staging/easycap/Kconfig"
|
||||
|
||||
endif # !STAGING_EXCLUDE_BUILD
|
||||
endif # STAGING
|
||||
|
|
|
@ -55,3 +55,4 @@ obj-$(CONFIG_ADIS16255) += adis16255/
|
|||
obj-$(CONFIG_FB_XGI) += xgifb/
|
||||
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
|
||||
obj-$(CONFIG_MSM_STAGING) += msm/
|
||||
obj-$(CONFIG_EASYCAP) += easycap/
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
config EASYCAP
|
||||
tristate "EasyCAP USB ID 05e1:0408 support"
|
||||
|
||||
---help---
|
||||
This is an integrated audio/video driver for EasyCAP cards with
|
||||
USB ID 05e1:0408. It supports two hardware variants:
|
||||
|
||||
* EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
|
||||
having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
|
||||
|
||||
* EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
|
||||
1, 2, 3, 4 and an unlabelled input cable for a microphone.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called easycap
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
obj-$(CONFIG_EASYCAP) += easycap.o
|
||||
|
||||
easycap-objs := easycap_main.o easycap_low.o easycap_sound.o
|
||||
easycap-objs += easycap_ioctl.o easycap_settings.o
|
||||
easycap-objs += easycap_testcard.o
|
||||
|
||||
EXTRA_CFLAGS += -Wall
|
||||
# Impose all or none of the following:
|
||||
EXTRA_CFLAGS += -DEASYCAP_IS_VIDEODEV_CLIENT
|
||||
EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_DEVICE_H
|
||||
EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_FOPS
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
|
||||
***********************************************************
|
||||
* EasyCAP USB 2.0 Video Adapter with Audio, Model DC60 *
|
||||
* and *
|
||||
* EasyCAP002 4-Channel USB 2.0 DVR *
|
||||
***********************************************************
|
||||
Mike Thomas <rmthomas@sciolus.org>
|
||||
|
||||
|
||||
|
||||
SUPPORTED HARDWARE
|
||||
------------------
|
||||
|
||||
This driver is intended for use with hardware having USB ID 05e1:0408.
|
||||
Two kinds of EasyCAP have this USB ID, namely:
|
||||
|
||||
* EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
|
||||
having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
|
||||
|
||||
* EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
|
||||
1, 2, 3, 4 and an unlabelled input cable for a microphone.
|
||||
|
||||
|
||||
BUILD OPTIONS AND DEPENDENCIES
|
||||
------------------------------
|
||||
|
||||
If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation
|
||||
the built module is entirely independent of the videodev module, and when
|
||||
the EasyCAP is physically plugged into a USB port the special files
|
||||
/dev/easycap0 and /dev/easysnd1 are created as video and sound sources
|
||||
respectively.
|
||||
|
||||
If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation
|
||||
the built easycap module is configured to register with the videodev module,
|
||||
in which case the special files created when the EasyCAP is plugged in are
|
||||
/dev/video0 and /dev/easysnd0. Use of the easycap module as a client of
|
||||
the videodev module has received very little testing as of June 2010.
|
||||
|
||||
|
||||
KNOWN BUILD PROBLEMS
|
||||
--------------------
|
||||
|
||||
(1) Recent gcc versions may generate the message:
|
||||
|
||||
warning: the frame size of .... bytes is larger than 1024 bytes
|
||||
|
||||
This warning can be suppressed by specifying in the Makefile:
|
||||
|
||||
EXTRA_CFLAGS += -Wframe-larger-than=8192
|
||||
|
||||
but it would be preferable to remove the cause of the warning.
|
||||
|
||||
|
||||
KNOWN RUNTIME ISSUES
|
||||
--------------------
|
||||
|
||||
(1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any
|
||||
output at start-up. Closing mplayer (or whatever the user program is) and
|
||||
restarting it restores normal performance without any other remedial action
|
||||
being necessary. The reason for this is not known.
|
||||
|
||||
(2) Intentionally, this driver will not stream material which is unambiguously
|
||||
identified by the hardware as copy-protected. The video output will freeze
|
||||
within about a minute when this situation arises.
|
||||
|
||||
(3) The controls for luminance, contrast, saturation, hue and volume may not
|
||||
always work properly.
|
||||
|
||||
(4) Reduced-resolution S-Video seems to suffer from moire artefacts. No
|
||||
attempt has yet been made to rememdy this.
|
||||
|
||||
|
||||
SUPPORTED TV STANDARDS AND RESOLUTIONS
|
||||
--------------------------------------
|
||||
|
||||
The following TV standards are natively supported by the hardware and are
|
||||
usable as (for example) the "norm=" parameter in the mplayer command:
|
||||
|
||||
PAL_BGHIN, NTSC_N_443,
|
||||
PAL_Nc, NTSC_N,
|
||||
SECAM, NTSC_M, NTSC_M_JP,
|
||||
PAL_60, NTSC_443,
|
||||
PAL_M.
|
||||
|
||||
The available picture sizes are:
|
||||
|
||||
at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240;
|
||||
at 30 frames per second: 720x480, 640x480, 360x240, 320x240;
|
||||
|
||||
|
||||
WHAT'S TESTED AND WHAT'S NOT
|
||||
----------------------------
|
||||
|
||||
This driver is known to work with mplayer, mencoder, tvtime and sufficiently
|
||||
recent versions of vlc. An interface to ffmpeg is implemented, but serious
|
||||
audio-video synchronization problems remain.
|
||||
|
||||
The driver is designed to support all the TV standards accepted by the
|
||||
hardware, but as yet it has actually been tested on only a few of these.
|
||||
|
||||
I have been unable to test and calibrate the S-video input myself because I
|
||||
do not possess any equipment with S-video output.
|
||||
|
||||
This driver does not understand the V4L1 IOCTL commands, so programs such
|
||||
as camorama are not compatible. There are reports that the driver does
|
||||
work with sufficiently recent (V4L2) versions of zoneminder, but I have not
|
||||
attempted to confirm this myself.
|
||||
|
||||
|
||||
UDEV RULES
|
||||
----------
|
||||
|
||||
In order that the special files /dev/easycap0 and /dev/easysnd1 are created
|
||||
with conveniently relaxed permissions when the EasyCAP is plugged in, a file
|
||||
is preferably to be provided in directory /etc/udev/rules.d with content:
|
||||
|
||||
ACTION!="add|change", GOTO="easycap_rules_end"
|
||||
ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \
|
||||
MODE="0666", OWNER="root", GROUP="root"
|
||||
LABEL="easycap_rules_end"
|
||||
|
||||
|
||||
ACKNOWLEGEMENTS AND REFERENCES
|
||||
------------------------------
|
||||
This driver makes use of information contained in the Syntek Semicon DC-1125
|
||||
Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/
|
||||
by Nicolas Vivien. Particularly useful has been a patch to the latter driver
|
||||
provided by Ivor Hewitt in January 2009. The NTSC implementation is taken
|
||||
from the work of Ben Trask.
|
||||
|
|
@ -0,0 +1,632 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* easycap.h *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THE FOLLOWING PARAMETERS ARE UNDEFINED:
|
||||
*
|
||||
* EASYCAP_DEBUG
|
||||
* EASYCAP_IS_VIDEODEV_CLIENT
|
||||
* EASYCAP_NEEDS_USBVIDEO_H
|
||||
* EASYCAP_NEEDS_V4L2_DEVICE_H
|
||||
* EASYCAP_NEEDS_V4L2_FOPS
|
||||
*
|
||||
* IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
|
||||
* OPTIONS.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#if (!defined(EASYCAP_H))
|
||||
#define EASYCAP_H
|
||||
|
||||
#if defined(EASYCAP_DEBUG)
|
||||
#if (9 < EASYCAP_DEBUG)
|
||||
#error Debug levels 0 to 9 are okay.\
|
||||
To achieve higher levels, remove this trap manually from easycap.h
|
||||
#endif
|
||||
#endif /*EASYCAP_DEBUG*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED:
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#undef PREFER_NTSC
|
||||
#undef EASYCAP_TESTCARD
|
||||
#undef EASYCAP_TESTTONE
|
||||
#undef LOCKFRAME
|
||||
#undef NOREADBACK
|
||||
#undef AUDIOTIME
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
*
|
||||
* DEFINE BRIDGER TO ACTIVATE THE ROUTINE FOR BRIDGING VIDEOTAPE DROPOUTS.
|
||||
*
|
||||
* *** UNDER DEVELOPMENT/TESTING - NOT READY YET!***
|
||||
*
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#undef BRIDGER
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
#if (!defined(__OLD_VIDIOC_))
|
||||
#define __OLD_VIDIOC_
|
||||
#endif /* !defined(__OLD_VIDIOC_) */
|
||||
|
||||
#include <media/v4l2-dev.h>
|
||||
|
||||
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
|
||||
#include <media/v4l2-device.h>
|
||||
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
#if (!defined(__OLD_VIDIOC_))
|
||||
#define __OLD_VIDIOC_
|
||||
#endif /* !defined(__OLD_VIDIOC_) */
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
#if defined(EASYCAP_NEEDS_USBVIDEO_H)
|
||||
#include <config/video/usbvideo.h>
|
||||
#endif /*EASYCAP_NEEDS_USBVIDEO_H*/
|
||||
|
||||
#if (!defined(PAGE_SIZE))
|
||||
#error "PAGE_SIZE not defined"
|
||||
#endif
|
||||
|
||||
#define STRINGIZE_AGAIN(x) #x
|
||||
#define STRINGIZE(x) STRINGIZE_AGAIN(x)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd
|
||||
*
|
||||
* EITHER EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60
|
||||
* with input cabling: AUDIO(L), AUDIO(R), CVBS, S-VIDEO.
|
||||
*
|
||||
* OR EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002
|
||||
* with input cabling: MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define USB_EASYCAP_VENDOR_ID 0x05e1
|
||||
#define USB_EASYCAP_PRODUCT_ID 0x0408
|
||||
|
||||
#define EASYCAP_DRIVER_VERSION "0.8"
|
||||
#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
|
||||
|
||||
#define USB_SKEL_MINOR_BASE 192
|
||||
#define VIDEO_DEVICE_MANY 8
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define SAA_0A_DEFAULT 0x7F
|
||||
#define SAA_0B_DEFAULT 0x3F
|
||||
#define SAA_0C_DEFAULT 0x2F
|
||||
#define SAA_0D_DEFAULT 0x00
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* VIDEO STREAMING PARAMETERS:
|
||||
* USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT
|
||||
* OF 3072 BYTES PER MICROFRAME for wMaxPacketSize.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define VIDEO_ISOC_BUFFER_MANY 16
|
||||
#define VIDEO_ISOC_ORDER 3
|
||||
#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER)
|
||||
#define USB_2_0_MAXPACKETSIZE 3072
|
||||
#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
|
||||
#error video_isoc_buffer[.] will not be big enough
|
||||
#endif
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* VIDEO BUFFERS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE)
|
||||
#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE)
|
||||
#define FIELD_BUFFER_MANY 4
|
||||
#define FRAME_BUFFER_MANY 6
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* AUDIO STREAMING PARAMETERS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define AUDIO_ISOC_BUFFER_MANY 16
|
||||
#define AUDIO_ISOC_ORDER 3
|
||||
#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* AUDIO BUFFERS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define AUDIO_FRAGMENT_MANY 32
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* STRUCTURE DEFINITIONS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct data_buffer {
|
||||
struct list_head list_head;
|
||||
void *pgo;
|
||||
void *pto;
|
||||
__u16 kount;
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct data_urb {
|
||||
struct list_head list_head;
|
||||
struct urb *purb;
|
||||
int isbuf;
|
||||
int length;
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
|
||||
* easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9
|
||||
* easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct easycap {
|
||||
|
||||
int ilk;
|
||||
bool microphone;
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
struct video_device *pvideo_device;
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
struct usb_device *pusb_device;
|
||||
struct usb_interface *pusb_interface;
|
||||
|
||||
struct kref kref;
|
||||
|
||||
struct mutex mutex_mmap_video[FRAME_BUFFER_MANY];
|
||||
struct mutex mutex_timeval0;
|
||||
struct mutex mutex_timeval1;
|
||||
|
||||
int queued[FRAME_BUFFER_MANY];
|
||||
int done[FRAME_BUFFER_MANY];
|
||||
|
||||
wait_queue_head_t wq_video;
|
||||
wait_queue_head_t wq_audio;
|
||||
|
||||
int input;
|
||||
int polled;
|
||||
int standard_offset;
|
||||
int format_offset;
|
||||
|
||||
int fps;
|
||||
int usec;
|
||||
int tolerate;
|
||||
int merit[180];
|
||||
|
||||
struct timeval timeval0;
|
||||
struct timeval timeval1;
|
||||
struct timeval timeval2;
|
||||
struct timeval timeval7;
|
||||
long long int dnbydt;
|
||||
|
||||
int video_interface;
|
||||
int video_altsetting_on;
|
||||
int video_altsetting_off;
|
||||
int video_endpointnumber;
|
||||
int video_isoc_maxframesize;
|
||||
int video_isoc_buffer_size;
|
||||
int video_isoc_framesperdesc;
|
||||
|
||||
int video_isoc_streaming;
|
||||
int video_isoc_sequence;
|
||||
int video_idle;
|
||||
int video_eof;
|
||||
int video_junk;
|
||||
|
||||
int fudge;
|
||||
|
||||
struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
|
||||
struct data_buffer \
|
||||
field_buffer[FIELD_BUFFER_MANY][(FIELD_BUFFER_SIZE/PAGE_SIZE)];
|
||||
struct data_buffer \
|
||||
frame_buffer[FRAME_BUFFER_MANY][(FRAME_BUFFER_SIZE/PAGE_SIZE)];
|
||||
|
||||
struct list_head urb_video_head;
|
||||
struct list_head *purb_video_head;
|
||||
|
||||
int vma_many;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* BUFFER INDICATORS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int field_fill; /* Field buffer being filled by easycap_complete(). */
|
||||
/* Bumped only by easycap_complete(). */
|
||||
int field_page; /* Page of field buffer page being filled by */
|
||||
/* easycap_complete(). */
|
||||
int field_read; /* Field buffer to be read by field2frame(). */
|
||||
/* Bumped only by easycap_complete(). */
|
||||
int frame_fill; /* Frame buffer being filled by field2frame(). */
|
||||
/* Bumped only by easycap_dqbuf() when */
|
||||
/* field2frame() has created a complete frame. */
|
||||
int frame_read; /* Frame buffer offered to user by DQBUF. */
|
||||
/* Set only by easycap_dqbuf() to trail frame_fill.*/
|
||||
int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IMAGE PROPERTIES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
__u32 pixelformat;
|
||||
__u32 field;
|
||||
int width;
|
||||
int height;
|
||||
int bytesperpixel;
|
||||
bool byteswaporder;
|
||||
bool decimatepixel;
|
||||
bool offerfields;
|
||||
int frame_buffer_used;
|
||||
int frame_buffer_many;
|
||||
int videofieldamount;
|
||||
|
||||
int brightness;
|
||||
int contrast;
|
||||
int saturation;
|
||||
int hue;
|
||||
|
||||
int allocation_video_urb;
|
||||
int allocation_video_page;
|
||||
int allocation_video_struct;
|
||||
int registered_video;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* SOUND PROPERTIES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int audio_interface;
|
||||
int audio_altsetting_on;
|
||||
int audio_altsetting_off;
|
||||
int audio_endpointnumber;
|
||||
int audio_isoc_maxframesize;
|
||||
int audio_isoc_buffer_size;
|
||||
int audio_isoc_framesperdesc;
|
||||
|
||||
int audio_isoc_streaming;
|
||||
int audio_idle;
|
||||
int audio_eof;
|
||||
int volume;
|
||||
int mute;
|
||||
|
||||
struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
|
||||
|
||||
struct list_head urb_audio_head;
|
||||
struct list_head *purb_audio_head;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* BUFFER INDICATORS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int audio_fill; /* Audio buffer being filled by easysnd_complete(). */
|
||||
/* Bumped only by easysnd_complete(). */
|
||||
int audio_read; /* Audio buffer page being read by easysnd_read(). */
|
||||
/* Set by easysnd_read() to trail audio_fill by */
|
||||
/* one fragment. */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* SOUND PROPERTIES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
int audio_buffer_many;
|
||||
|
||||
int allocation_audio_urb;
|
||||
int allocation_audio_page;
|
||||
int allocation_audio_struct;
|
||||
int registered_audio;
|
||||
|
||||
long long int audio_sample;
|
||||
long long int audio_niveau;
|
||||
long long int audio_square;
|
||||
|
||||
struct data_buffer audio_buffer[];
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct easycap_standard {
|
||||
__u16 mask;
|
||||
struct v4l2_standard v4l2_standard;
|
||||
};
|
||||
struct easycap_format {
|
||||
__u16 mask;
|
||||
char name[128];
|
||||
struct v4l2_format v4l2_format;
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* VIDEO FUNCTION PROTOTYPES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void easycap_complete(struct urb *);
|
||||
int easycap_open(struct inode *, struct file *);
|
||||
int easycap_release(struct inode *, struct file *);
|
||||
int easycap_ioctl(struct inode *, struct file *, \
|
||||
unsigned int, unsigned long);
|
||||
|
||||
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
|
||||
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
|
||||
int easycap_open_noinode(struct file *);
|
||||
int easycap_release_noinode(struct file *);
|
||||
long easycap_ioctl_noinode(struct file *, \
|
||||
unsigned int, unsigned long);
|
||||
int videodev_release(struct video_device *);
|
||||
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
|
||||
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
|
||||
|
||||
unsigned int easycap_poll(struct file *, poll_table *);
|
||||
int easycap_mmap(struct file *, struct vm_area_struct *);
|
||||
int easycap_usb_probe(struct usb_interface *, \
|
||||
const struct usb_device_id *);
|
||||
void easycap_usb_disconnect(struct usb_interface *);
|
||||
void easycap_delete(struct kref *);
|
||||
|
||||
void easycap_vma_open(struct vm_area_struct *);
|
||||
void easycap_vma_close(struct vm_area_struct *);
|
||||
int easycap_vma_fault(struct vm_area_struct *, struct vm_fault *);
|
||||
int easycap_dqbuf(struct easycap *, int);
|
||||
int submit_video_urbs(struct easycap *);
|
||||
int kill_video_urbs(struct easycap *);
|
||||
int field2frame(struct easycap *);
|
||||
int redaub(struct easycap *, void *, void *, \
|
||||
int, int, __u8, __u8, bool);
|
||||
void debrief(struct easycap *);
|
||||
void sayreadonly(struct easycap *);
|
||||
void easycap_testcard(struct easycap *, int);
|
||||
int explain_ioctl(__u32);
|
||||
int explain_cid(__u32);
|
||||
int fillin_formats(void);
|
||||
int adjust_standard(struct easycap *, v4l2_std_id);
|
||||
int adjust_format(struct easycap *, __u32, __u32, __u32, \
|
||||
int, bool);
|
||||
int adjust_brightness(struct easycap *, int);
|
||||
int adjust_contrast(struct easycap *, int);
|
||||
int adjust_saturation(struct easycap *, int);
|
||||
int adjust_hue(struct easycap *, int);
|
||||
int adjust_volume(struct easycap *, int);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* AUDIO FUNCTION PROTOTYPES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void easysnd_complete(struct urb *);
|
||||
ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *);
|
||||
int easysnd_open(struct inode *, struct file *);
|
||||
int easysnd_release(struct inode *, struct file *);
|
||||
int easysnd_ioctl(struct inode *, struct file *, \
|
||||
unsigned int, unsigned long);
|
||||
unsigned int easysnd_poll(struct file *, poll_table *);
|
||||
void easysnd_delete(struct kref *);
|
||||
int submit_audio_urbs(struct easycap *);
|
||||
int kill_audio_urbs(struct easycap *);
|
||||
void easysnd_testtone(struct easycap *, int);
|
||||
int audio_setup(struct easycap *);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* LOW-LEVEL FUNCTION PROTOTYPES
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int audio_gainget(struct usb_device *);
|
||||
int audio_gainset(struct usb_device *, __s8);
|
||||
|
||||
int set_interface(struct usb_device *, __u16);
|
||||
int wakeup_device(struct usb_device *);
|
||||
int confirm_resolution(struct usb_device *);
|
||||
int confirm_stream(struct usb_device *);
|
||||
|
||||
int setup_stk(struct usb_device *);
|
||||
int setup_saa(struct usb_device *);
|
||||
int setup_vt(struct usb_device *);
|
||||
int check_stk(struct usb_device *);
|
||||
int check_saa(struct usb_device *);
|
||||
int ready_saa(struct usb_device *);
|
||||
int merit_saa(struct usb_device *);
|
||||
int check_vt(struct usb_device *);
|
||||
int select_input(struct usb_device *, int, int);
|
||||
int set_resolution(struct usb_device *, \
|
||||
__u16, __u16, __u16, __u16);
|
||||
|
||||
int read_saa(struct usb_device *, __u16);
|
||||
int read_stk(struct usb_device *, __u32);
|
||||
int write_saa(struct usb_device *, __u16, __u16);
|
||||
int wait_i2c(struct usb_device *);
|
||||
int write_000(struct usb_device *, __u16, __u16);
|
||||
int start_100(struct usb_device *);
|
||||
int stop_100(struct usb_device *);
|
||||
int write_300(struct usb_device *);
|
||||
int read_vt(struct usb_device *, __u16);
|
||||
int write_vt(struct usb_device *, __u16, __u16);
|
||||
|
||||
int set2to78(struct usb_device *);
|
||||
int set2to93(struct usb_device *);
|
||||
|
||||
int regset(struct usb_device *, __u16, __u16);
|
||||
int regget(struct usb_device *, __u16, void *);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct signed_div_result {
|
||||
long long int quotient;
|
||||
unsigned long long int remainder;
|
||||
} signed_div(long long int, long long int);
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
|
||||
* ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND.
|
||||
* THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT
|
||||
* ONLY MUST THE PARAMETER
|
||||
* STANDARD_MANY
|
||||
* BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE
|
||||
* NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS
|
||||
* MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN
|
||||
* ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define PAL_BGHIN 0
|
||||
#define PAL_Nc 2
|
||||
#define SECAM 4
|
||||
#define NTSC_N 6
|
||||
#define NTSC_N_443 8
|
||||
#define NTSC_M 1
|
||||
#define NTSC_443 3
|
||||
#define NTSC_M_JP 5
|
||||
#define PAL_60 7
|
||||
#define PAL_M 9
|
||||
#define STANDARD_MANY 10
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* ENUMS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
enum {
|
||||
AT_720x576,
|
||||
AT_704x576,
|
||||
AT_640x480,
|
||||
AT_720x480,
|
||||
AT_360x288,
|
||||
AT_320x240,
|
||||
AT_360x240,
|
||||
RESOLUTION_MANY
|
||||
};
|
||||
enum {
|
||||
FMT_UYVY,
|
||||
FMT_YUY2,
|
||||
FMT_RGB24,
|
||||
FMT_RGB32,
|
||||
FMT_BGR24,
|
||||
FMT_BGR32,
|
||||
PIXELFORMAT_MANY
|
||||
};
|
||||
enum {
|
||||
FIELD_NONE,
|
||||
FIELD_INTERLACED,
|
||||
FIELD_ALTERNATE,
|
||||
INTERLACE_MANY
|
||||
};
|
||||
#define SETTINGS_MANY (STANDARD_MANY * \
|
||||
RESOLUTION_MANY * \
|
||||
2 * \
|
||||
PIXELFORMAT_MANY * \
|
||||
INTERLACE_MANY)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* MACROS
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define GET(X, Y, Z) do { \
|
||||
int rc; \
|
||||
*(Z) = (__u16)0; \
|
||||
rc = regget(X, Y, Z); \
|
||||
if (0 > rc) { \
|
||||
JOT(8, ":-(%i\n", __LINE__); return(rc); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SET(X, Y, Z) do { \
|
||||
int rc; \
|
||||
rc = regset(X, Y, Z); \
|
||||
if (0 > rc) { \
|
||||
JOT(8, ":-(%i\n", __LINE__); return(rc); \
|
||||
} \
|
||||
} while (0)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#define SAY(format, args...) do { \
|
||||
printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#if defined(EASYCAP_DEBUG)
|
||||
#define JOT(n, format, args...) do { \
|
||||
if (n <= easycap_debug) { \
|
||||
printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define JOT(n, format, args...) do {} while (0)
|
||||
#endif /*EASYCAP_DEBUG*/
|
||||
|
||||
#define POUT JOT(8, ":-(in file %s line %4i\n", __FILE__, __LINE__)
|
||||
|
||||
#define MICROSECONDS(X, Y) \
|
||||
((1000000*((long long int)(X.tv_sec - Y.tv_sec))) + \
|
||||
(long long int)(X.tv_usec - Y.tv_usec))
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* (unsigned char *)P pointer to next byte pair
|
||||
* (long int *)X pointer to accumulating count
|
||||
* (long int *)Y pointer to accumulating sum
|
||||
* (long long int *)Z pointer to accumulating sum of squares
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
#define SUMMER(P, X, Y, Z) do { \
|
||||
unsigned char *p; \
|
||||
unsigned int u0, u1, u2; \
|
||||
long int s; \
|
||||
p = (unsigned char *)(P); \
|
||||
u0 = (unsigned int) (*p); \
|
||||
u1 = (unsigned int) (*(p + 1)); \
|
||||
u2 = (unsigned int) ((u1 << 8) | u0); \
|
||||
if (0x8000 & u2) \
|
||||
s = -(long int)(0x7FFF & (~u2)); \
|
||||
else \
|
||||
s = (long int)(0x7FFF & u2); \
|
||||
*((X)) += (long int) 1; \
|
||||
*((Y)) += (long int) s; \
|
||||
*((Z)) += ((long long int)(s) * (long long int)(s)); \
|
||||
} while (0)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#endif /*EASYCAP_H*/
|
|
@ -0,0 +1,27 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* easycap_debug.h *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
extern int easycap_debug;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,29 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* easycap_ioctl.h *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
extern struct easycap_format easycap_format[];
|
||||
extern struct v4l2_queryctrl easycap_control[];
|
||||
extern unsigned int audio_bytes_per_fragment;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,489 @@
|
|||
/******************************************************************************
|
||||
* *
|
||||
* easycap_settings.c *
|
||||
* *
|
||||
******************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "easycap.h"
|
||||
#include "easycap_debug.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
|
||||
* 0 => 25 fps
|
||||
* 1 => 30 fps
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct easycap_standard easycap_standard[] = {
|
||||
{
|
||||
.mask = 0x000F & PAL_BGHIN ,
|
||||
.v4l2_standard = {
|
||||
.index = PAL_BGHIN,
|
||||
.id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \
|
||||
V4L2_STD_PAL_I | V4L2_STD_PAL_N),
|
||||
.name = "PAL_BGHIN",
|
||||
.frameperiod = {1, 25},
|
||||
.framelines = 625,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & NTSC_N_443 ,
|
||||
.v4l2_standard = {
|
||||
.index = NTSC_N_443,
|
||||
.id = V4L2_STD_UNKNOWN,
|
||||
.name = "NTSC_N_443",
|
||||
.frameperiod = {1, 25},
|
||||
.framelines = 480,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & PAL_Nc ,
|
||||
.v4l2_standard = {
|
||||
.index = PAL_Nc,
|
||||
.id = V4L2_STD_PAL_Nc,
|
||||
.name = "PAL_Nc",
|
||||
.frameperiod = {1, 25},
|
||||
.framelines = 625,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & NTSC_N ,
|
||||
.v4l2_standard = {
|
||||
.index = NTSC_N,
|
||||
.id = V4L2_STD_UNKNOWN,
|
||||
.name = "NTSC_N",
|
||||
.frameperiod = {1, 25},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & SECAM ,
|
||||
.v4l2_standard = {
|
||||
.index = SECAM,
|
||||
.id = V4L2_STD_SECAM,
|
||||
.name = "SECAM",
|
||||
.frameperiod = {1, 25},
|
||||
.framelines = 625,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & NTSC_M ,
|
||||
.v4l2_standard = {
|
||||
.index = NTSC_M,
|
||||
.id = V4L2_STD_NTSC_M,
|
||||
.name = "NTSC_M",
|
||||
.frameperiod = {1, 30},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & NTSC_M_JP ,
|
||||
.v4l2_standard = {
|
||||
.index = NTSC_M_JP,
|
||||
.id = V4L2_STD_NTSC_M_JP,
|
||||
.name = "NTSC_M_JP",
|
||||
.frameperiod = {1, 30},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & PAL_60 ,
|
||||
.v4l2_standard = {
|
||||
.index = PAL_60,
|
||||
.id = V4L2_STD_PAL_60,
|
||||
.name = "PAL_60",
|
||||
.frameperiod = {1, 30},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & NTSC_443 ,
|
||||
.v4l2_standard = {
|
||||
.index = NTSC_443,
|
||||
.id = V4L2_STD_NTSC_443,
|
||||
.name = "NTSC_443",
|
||||
.frameperiod = {1, 30},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0x000F & PAL_M ,
|
||||
.v4l2_standard = {
|
||||
.index = PAL_M,
|
||||
.id = V4L2_STD_PAL_M,
|
||||
.name = "PAL_M",
|
||||
.frameperiod = {1, 30},
|
||||
.framelines = 525,
|
||||
.reserved = {0, 0, 0, 0}
|
||||
}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.mask = 0xFFFF
|
||||
}
|
||||
};
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THE 16-BIT easycap_format.mask HAS MEANING:
|
||||
* (least significant) BIT 0: 0 => PAL, 25 FPS; 1 => NTSC, 30 FPS
|
||||
* BITS 1-3: RESERVED FOR DIFFERENTIATING STANDARDS
|
||||
* BITS 4-7: NUMBER OF BYTES PER PIXEL
|
||||
* BIT 8: 0 => NATIVE BYTE ORDER; 1 => SWAPPED
|
||||
* BITS 9-10: RESERVED FOR OTHER BYTE PERMUTATIONS
|
||||
* BIT 11: 0 => UNDECIMATED; 1 => DECIMATED
|
||||
* BIT 12: 0 => OFFER FRAMES; 1 => OFFER FIELDS
|
||||
* (most significant) BITS 13-15: RESERVED FOR OTHER FIELD ORDER OPTIONS
|
||||
* IT FOLLOWS THAT:
|
||||
* bytesperpixel IS ((0x00F0 & easycap_format.mask) >> 4)
|
||||
* byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask))
|
||||
*
|
||||
* decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask))
|
||||
*
|
||||
* offerfields IS true IF (0 != (0x1000 & easycap_format.mask))
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
struct easycap_format easycap_format[1 + SETTINGS_MANY];
|
||||
|
||||
int
|
||||
fillin_formats(void)
|
||||
{
|
||||
int i, j, k, m, n;
|
||||
__u32 width, height, pixelformat, bytesperline, sizeimage;
|
||||
__u32 field, colorspace;
|
||||
__u16 mask1, mask2, mask3, mask4;
|
||||
char name1[32], name2[32], name3[32], name4[32];
|
||||
|
||||
for (i = 0, n = 0; i < STANDARD_MANY; i++) {
|
||||
mask1 = 0x0000;
|
||||
switch (i) {
|
||||
case PAL_BGHIN: {
|
||||
mask1 = PAL_BGHIN;
|
||||
strcpy(&name1[0], "PAL_BGHIN");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
|
||||
break;
|
||||
}
|
||||
case SECAM: {
|
||||
mask1 = SECAM;
|
||||
strcpy(&name1[0], "SECAM");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
|
||||
break;
|
||||
}
|
||||
case PAL_Nc: {
|
||||
mask1 = PAL_Nc;
|
||||
strcpy(&name1[0], "PAL_Nc");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
|
||||
break;
|
||||
}
|
||||
case PAL_60: {
|
||||
mask1 = PAL_60;
|
||||
strcpy(&name1[0], "PAL_60");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
|
||||
break;
|
||||
}
|
||||
case PAL_M: {
|
||||
mask1 = PAL_M;
|
||||
strcpy(&name1[0], "PAL_M");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
|
||||
break;
|
||||
}
|
||||
case NTSC_M: {
|
||||
mask1 = NTSC_M;
|
||||
strcpy(&name1[0], "NTSC_M");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
|
||||
break;
|
||||
}
|
||||
case NTSC_443: {
|
||||
mask1 = NTSC_443;
|
||||
strcpy(&name1[0], "NTSC_443");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
|
||||
break;
|
||||
}
|
||||
case NTSC_M_JP: {
|
||||
mask1 = NTSC_M_JP;
|
||||
strcpy(&name1[0], "NTSC_M_JP");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
|
||||
break;
|
||||
}
|
||||
case NTSC_N: {
|
||||
mask1 = NTSC_M;
|
||||
strcpy(&name1[0], "NTSC_N");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
|
||||
break;
|
||||
}
|
||||
case NTSC_N_443: {
|
||||
mask1 = NTSC_N_443;
|
||||
strcpy(&name1[0], "NTSC_N_443");
|
||||
colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (j = 0; j < RESOLUTION_MANY; j++) {
|
||||
mask2 = 0x0000;
|
||||
switch (j) {
|
||||
case AT_720x576: {
|
||||
if (0x1 & mask1)
|
||||
continue;
|
||||
strcpy(&name2[0], "_AT_720x576");
|
||||
width = 720; height = 576; break;
|
||||
}
|
||||
case AT_704x576: {
|
||||
if (0x1 & mask1)
|
||||
continue;
|
||||
strcpy(&name2[0], "_AT_704x576");
|
||||
width = 704; height = 576; break;
|
||||
}
|
||||
case AT_640x480: {
|
||||
strcpy(&name2[0], "_AT_640x480");
|
||||
width = 640; height = 480; break;
|
||||
}
|
||||
case AT_720x480: {
|
||||
if (!(0x1 & mask1))
|
||||
continue;
|
||||
strcpy(&name2[0], "_AT_720x480");
|
||||
width = 720; height = 480; break;
|
||||
}
|
||||
case AT_360x288: {
|
||||
if (0x1 & mask1)
|
||||
continue;
|
||||
strcpy(&name2[0], "_AT_360x288");
|
||||
width = 360; height = 288; mask2 = 0x0800; break;
|
||||
}
|
||||
case AT_320x240: {
|
||||
strcpy(&name2[0], "_AT_320x240");
|
||||
width = 320; height = 240; mask2 = 0x0800; break;
|
||||
}
|
||||
case AT_360x240: {
|
||||
if (!(0x1 & mask1))
|
||||
continue;
|
||||
strcpy(&name2[0], "_AT_360x240");
|
||||
width = 360; height = 240; mask2 = 0x0800; break;
|
||||
}
|
||||
default:
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (k = 0; k < PIXELFORMAT_MANY; k++) {
|
||||
mask3 = 0x0000;
|
||||
switch (k) {
|
||||
case FMT_UYVY: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_UYVY));
|
||||
pixelformat = V4L2_PIX_FMT_UYVY;
|
||||
mask3 |= (0x02 << 4);
|
||||
break;
|
||||
}
|
||||
case FMT_YUY2: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_YUY2));
|
||||
pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
mask3 |= (0x02 << 4);
|
||||
mask3 |= 0x0100;
|
||||
break;
|
||||
}
|
||||
case FMT_RGB24: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_RGB24));
|
||||
pixelformat = V4L2_PIX_FMT_RGB24;
|
||||
mask3 |= (0x03 << 4);
|
||||
break;
|
||||
}
|
||||
case FMT_RGB32: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_RGB32));
|
||||
pixelformat = V4L2_PIX_FMT_RGB32;
|
||||
mask3 |= (0x04 << 4);
|
||||
break;
|
||||
}
|
||||
case FMT_BGR24: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_BGR24));
|
||||
pixelformat = V4L2_PIX_FMT_BGR24;
|
||||
mask3 |= (0x03 << 4);
|
||||
mask3 |= 0x0100;
|
||||
break;
|
||||
}
|
||||
case FMT_BGR32: {
|
||||
strcpy(&name3[0], "_" STRINGIZE(FMT_BGR32));
|
||||
pixelformat = V4L2_PIX_FMT_BGR32;
|
||||
mask3 |= (0x04 << 4);
|
||||
mask3 |= 0x0100;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -3;
|
||||
}
|
||||
bytesperline = width * ((mask3 & 0x00F0) >> 4);
|
||||
sizeimage = bytesperline * height;
|
||||
|
||||
for (m = 0; m < INTERLACE_MANY; m++) {
|
||||
mask4 = 0x0000;
|
||||
switch (m) {
|
||||
case FIELD_NONE: {
|
||||
strcpy(&name4[0], "-n");
|
||||
field = V4L2_FIELD_NONE;
|
||||
break;
|
||||
}
|
||||
case FIELD_INTERLACED: {
|
||||
strcpy(&name4[0], "-i");
|
||||
field = V4L2_FIELD_INTERLACED;
|
||||
break;
|
||||
}
|
||||
case FIELD_ALTERNATE: {
|
||||
strcpy(&name4[0], "-a");
|
||||
mask4 |= 0x1000;
|
||||
field = V4L2_FIELD_ALTERNATE;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -4;
|
||||
}
|
||||
if (SETTINGS_MANY <= n)
|
||||
return -5;
|
||||
strcpy(&easycap_format[n].name[0], &name1[0]);
|
||||
strcat(&easycap_format[n].name[0], &name2[0]);
|
||||
strcat(&easycap_format[n].name[0], &name3[0]);
|
||||
strcat(&easycap_format[n].name[0], &name4[0]);
|
||||
easycap_format[n].mask = \
|
||||
mask1 | mask2 | mask3 | mask4;
|
||||
easycap_format[n].v4l2_format\
|
||||
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.width = width;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.height = height;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.pixelformat = pixelformat;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.field = field;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.bytesperline = bytesperline;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.sizeimage = sizeimage;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.colorspace = colorspace;
|
||||
easycap_format[n].v4l2_format\
|
||||
.fmt.pix.priv = 0;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((1 + SETTINGS_MANY) <= n)
|
||||
return -6;
|
||||
easycap_format[n].mask = 0xFFFF;
|
||||
return n;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
struct v4l2_queryctrl easycap_control[] = \
|
||||
{{
|
||||
.id = V4L2_CID_BRIGHTNESS,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Brightness",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = SAA_0A_DEFAULT,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = V4L2_CID_CONTRAST,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Contrast",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = SAA_0B_DEFAULT + 128,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = V4L2_CID_SATURATION,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Saturation",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = SAA_0C_DEFAULT + 128,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = V4L2_CID_HUE,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Hue",
|
||||
.minimum = 0,
|
||||
.maximum = 255,
|
||||
.step = 1,
|
||||
.default_value = SAA_0D_DEFAULT + 128,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_VOLUME,
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.name = "Volume",
|
||||
.minimum = 0,
|
||||
.maximum = 31,
|
||||
.step = 1,
|
||||
.default_value = 16,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = V4L2_CID_AUDIO_MUTE,
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.name = "Mute",
|
||||
.default_value = true,
|
||||
.flags = 0,
|
||||
.reserved = {0, 0}
|
||||
},
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
{
|
||||
.id = 0xFFFFFFFF
|
||||
}
|
||||
};
|
||||
/*****************************************************************************/
|
|
@ -0,0 +1,973 @@
|
|||
/******************************************************************************
|
||||
* *
|
||||
* easycap_sound.c *
|
||||
* *
|
||||
* Audio driver for EasyCAP USB2.0 Video Capture Device DC60 *
|
||||
* *
|
||||
* *
|
||||
******************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "easycap.h"
|
||||
#include "easycap_debug.h"
|
||||
#include "easycap_sound.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS
|
||||
* PROVIDED peasycap->audio_idle IS ZER0. REGARDLESS OF THIS BEING TRUE,
|
||||
* IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
easysnd_complete(struct urb *purb)
|
||||
{
|
||||
static int mt;
|
||||
struct easycap *peasycap;
|
||||
struct data_buffer *paudio_buffer;
|
||||
char errbuf[16];
|
||||
__u8 *p1, *p2;
|
||||
__s16 s16;
|
||||
int i, j, more, much, leap, rc;
|
||||
|
||||
JOT(16, "\n");
|
||||
|
||||
if (NULL == purb) {
|
||||
SAY("ERROR: purb is NULL\n");
|
||||
return;
|
||||
}
|
||||
peasycap = purb->context;
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
return;
|
||||
}
|
||||
much = 0;
|
||||
|
||||
|
||||
if (peasycap->audio_idle) {
|
||||
JOT(16, "%i=audio_idle %i=audio_isoc_streaming\n", \
|
||||
peasycap->audio_idle, peasycap->audio_isoc_streaming);
|
||||
if (peasycap->audio_isoc_streaming) {
|
||||
rc = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (0 != rc) {
|
||||
SAY("ERROR: while %i=audio_idle, " \
|
||||
"usb_submit_urb() failed with rc:\n", \
|
||||
peasycap->audio_idle);
|
||||
switch (rc) {
|
||||
case -ENOMEM: {
|
||||
SAY("ENOMEM\n"); break;
|
||||
}
|
||||
case -ENODEV: {
|
||||
SAY("ENODEV\n"); break;
|
||||
}
|
||||
case -ENXIO: {
|
||||
SAY("ENXIO\n"); break;
|
||||
}
|
||||
case -EINVAL: {
|
||||
SAY("EINVAL\n"); break;
|
||||
}
|
||||
case -EAGAIN: {
|
||||
SAY("EAGAIN\n"); break;
|
||||
}
|
||||
case -EFBIG: {
|
||||
SAY("EFBIG\n"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
SAY("EPIPE\n"); break;
|
||||
}
|
||||
case -EMSGSIZE: {
|
||||
SAY("EMSGSIZE\n"); break;
|
||||
}
|
||||
default: {
|
||||
SAY("0x%08X\n", rc); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (purb->status) {
|
||||
if (-ESHUTDOWN == purb->status) {
|
||||
JOT(16, "immediate return because -ESHUTDOWN=purb->status\n");
|
||||
return;
|
||||
}
|
||||
SAY("ERROR: non-zero urb status:\n");
|
||||
switch (purb->status) {
|
||||
case -EINPROGRESS: {
|
||||
SAY("-EINPROGRESS\n"); break;
|
||||
}
|
||||
case -ENOSR: {
|
||||
SAY("-ENOSR\n"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
SAY("-EPIPE\n"); break;
|
||||
}
|
||||
case -EOVERFLOW: {
|
||||
SAY("-EOVERFLOW\n"); break;
|
||||
}
|
||||
case -EPROTO: {
|
||||
SAY("-EPROTO\n"); break;
|
||||
}
|
||||
case -EILSEQ: {
|
||||
SAY("-EILSEQ\n"); break;
|
||||
}
|
||||
case -ETIMEDOUT: {
|
||||
SAY("-ETIMEDOUT\n"); break;
|
||||
}
|
||||
case -EMSGSIZE: {
|
||||
SAY("-EMSGSIZE\n"); break;
|
||||
}
|
||||
case -EOPNOTSUPP: {
|
||||
SAY("-EOPNOTSUPP\n"); break;
|
||||
}
|
||||
case -EPFNOSUPPORT: {
|
||||
SAY("-EPFNOSUPPORT\n"); break;
|
||||
}
|
||||
case -EAFNOSUPPORT: {
|
||||
SAY("-EAFNOSUPPORT\n"); break;
|
||||
}
|
||||
case -EADDRINUSE: {
|
||||
SAY("-EADDRINUSE\n"); break;
|
||||
}
|
||||
case -EADDRNOTAVAIL: {
|
||||
SAY("-EADDRNOTAVAIL\n"); break;
|
||||
}
|
||||
case -ENOBUFS: {
|
||||
SAY("-ENOBUFS\n"); break;
|
||||
}
|
||||
case -EISCONN: {
|
||||
SAY("-EISCONN\n"); break;
|
||||
}
|
||||
case -ENOTCONN: {
|
||||
SAY("-ENOTCONN\n"); break;
|
||||
}
|
||||
case -ESHUTDOWN: {
|
||||
SAY("-ESHUTDOWN\n"); break;
|
||||
}
|
||||
case -ENOENT: {
|
||||
SAY("-ENOENT\n"); break;
|
||||
}
|
||||
case -ECONNRESET: {
|
||||
SAY("-ECONNRESET\n"); break;
|
||||
}
|
||||
default: {
|
||||
SAY("unknown error code 0x%08X\n", purb->status); break;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* RESUBMIT THIS URB AFTER AN ERROR
|
||||
*
|
||||
* (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH)
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (peasycap->audio_isoc_streaming) {
|
||||
rc = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (0 != rc) {
|
||||
SAY("ERROR: while %i=audio_idle, usb_submit_urb() "
|
||||
"failed with rc:\n", peasycap->audio_idle);
|
||||
switch (rc) {
|
||||
case -ENOMEM: {
|
||||
SAY("ENOMEM\n"); break;
|
||||
}
|
||||
case -ENODEV: {
|
||||
SAY("ENODEV\n"); break;
|
||||
}
|
||||
case -ENXIO: {
|
||||
SAY("ENXIO\n"); break;
|
||||
}
|
||||
case -EINVAL: {
|
||||
SAY("EINVAL\n"); break;
|
||||
}
|
||||
case -EAGAIN: {
|
||||
SAY("EAGAIN\n"); break;
|
||||
}
|
||||
case -EFBIG: {
|
||||
SAY("EFBIG\n"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
SAY("EPIPE\n"); break;
|
||||
}
|
||||
case -EMSGSIZE: {
|
||||
SAY("EMSGSIZE\n"); break;
|
||||
}
|
||||
default: {
|
||||
SAY("0x%08X\n", rc); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* PROCEED HERE WHEN NO ERROR
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
for (i = 0; i < purb->number_of_packets; i++) {
|
||||
switch (purb->iso_frame_desc[i].status) {
|
||||
case 0: {
|
||||
strcpy(&errbuf[0], "OK"); break;
|
||||
}
|
||||
case -ENOENT: {
|
||||
strcpy(&errbuf[0], "-ENOENT"); break;
|
||||
}
|
||||
case -EINPROGRESS: {
|
||||
strcpy(&errbuf[0], "-EINPROGRESS"); break;
|
||||
}
|
||||
case -EPROTO: {
|
||||
strcpy(&errbuf[0], "-EPROTO"); break;
|
||||
}
|
||||
case -EILSEQ: {
|
||||
strcpy(&errbuf[0], "-EILSEQ"); break;
|
||||
}
|
||||
case -ETIME: {
|
||||
strcpy(&errbuf[0], "-ETIME"); break;
|
||||
}
|
||||
case -ETIMEDOUT: {
|
||||
strcpy(&errbuf[0], "-ETIMEDOUT"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
strcpy(&errbuf[0], "-EPIPE"); break;
|
||||
}
|
||||
case -ECOMM: {
|
||||
strcpy(&errbuf[0], "-ECOMM"); break;
|
||||
}
|
||||
case -ENOSR: {
|
||||
strcpy(&errbuf[0], "-ENOSR"); break;
|
||||
}
|
||||
case -EOVERFLOW: {
|
||||
strcpy(&errbuf[0], "-EOVERFLOW"); break;
|
||||
}
|
||||
case -EREMOTEIO: {
|
||||
strcpy(&errbuf[0], "-EREMOTEIO"); break;
|
||||
}
|
||||
case -ENODEV: {
|
||||
strcpy(&errbuf[0], "-ENODEV"); break;
|
||||
}
|
||||
case -EXDEV: {
|
||||
strcpy(&errbuf[0], "-EXDEV"); break;
|
||||
}
|
||||
case -EINVAL: {
|
||||
strcpy(&errbuf[0], "-EINVAL"); break;
|
||||
}
|
||||
case -ECONNRESET: {
|
||||
strcpy(&errbuf[0], "-ECONNRESET"); break;
|
||||
}
|
||||
case -ESHUTDOWN: {
|
||||
strcpy(&errbuf[0], "-ESHUTDOWN"); break;
|
||||
}
|
||||
default: {
|
||||
strcpy(&errbuf[0], "UNKNOWN"); break;
|
||||
}
|
||||
}
|
||||
if ((!purb->iso_frame_desc[i].status) && 0) {
|
||||
JOT(16, "frame[%2i]: %i=status{=%16s} " \
|
||||
"%5i=actual " \
|
||||
"%5i=length " \
|
||||
"%3i=offset\n", \
|
||||
i, purb->iso_frame_desc[i].status, &errbuf[0],
|
||||
purb->iso_frame_desc[i].actual_length,
|
||||
purb->iso_frame_desc[i].length,
|
||||
purb->iso_frame_desc[i].offset);
|
||||
}
|
||||
if (!purb->iso_frame_desc[i].status) {
|
||||
more = purb->iso_frame_desc[i].actual_length;
|
||||
|
||||
#if defined(TESTTONE)
|
||||
if (!more)
|
||||
more = purb->iso_frame_desc[i].length;
|
||||
#endif
|
||||
|
||||
if (!more)
|
||||
mt++;
|
||||
else {
|
||||
if (mt) {
|
||||
JOT(16, "%4i empty audio urb frames\n", mt);
|
||||
mt = 0;
|
||||
}
|
||||
|
||||
p1 = (__u8 *)(purb->transfer_buffer + \
|
||||
purb->iso_frame_desc[i].offset);
|
||||
|
||||
leap = 0;
|
||||
p1 += leap;
|
||||
more -= leap;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER,
|
||||
* CONVERTING 8-BIT SAMPLES TO 16-BIT SIGNED LITTLE-ENDED SAMPLES IF NECESSARY
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
while (more) {
|
||||
if (0 > more) {
|
||||
SAY("easysnd_complete: MISTAKE: " \
|
||||
"more is negative\n");
|
||||
return;
|
||||
}
|
||||
if (audio_buffer_page_many <= \
|
||||
peasycap->audio_fill) {
|
||||
SAY("ERROR: bad " \
|
||||
"peasycap->audio_fill\n");
|
||||
return;
|
||||
}
|
||||
|
||||
paudio_buffer = &peasycap->audio_buffer\
|
||||
[peasycap->audio_fill];
|
||||
if (PAGE_SIZE < (paudio_buffer->pto - \
|
||||
paudio_buffer->pgo)) {
|
||||
SAY("ERROR: bad paudio_buffer->pto\n");
|
||||
return;
|
||||
}
|
||||
if (PAGE_SIZE == (paudio_buffer->pto - \
|
||||
paudio_buffer->pgo)) {
|
||||
|
||||
#if defined(TESTTONE)
|
||||
easysnd_testtone(peasycap, \
|
||||
peasycap->audio_fill);
|
||||
#endif /*TESTTONE*/
|
||||
|
||||
paudio_buffer->pto = \
|
||||
paudio_buffer->pgo;
|
||||
(peasycap->audio_fill)++;
|
||||
if (audio_buffer_page_many <= \
|
||||
peasycap->audio_fill)
|
||||
peasycap->audio_fill = 0;
|
||||
|
||||
JOT(12, "bumped peasycap->" \
|
||||
"audio_fill to %i\n", \
|
||||
peasycap->audio_fill);
|
||||
|
||||
paudio_buffer = &peasycap->\
|
||||
audio_buffer\
|
||||
[peasycap->audio_fill];
|
||||
paudio_buffer->pto = \
|
||||
paudio_buffer->pgo;
|
||||
|
||||
if (!(peasycap->audio_fill % \
|
||||
audio_pages_per_fragment)) {
|
||||
JOT(12, "wakeup call on wq_" \
|
||||
"audio, %i=frag reading %i" \
|
||||
"=fragment fill\n", \
|
||||
(peasycap->audio_read / \
|
||||
audio_pages_per_fragment), \
|
||||
(peasycap->audio_fill / \
|
||||
audio_pages_per_fragment));
|
||||
wake_up_interruptible\
|
||||
(&(peasycap->wq_audio));
|
||||
}
|
||||
}
|
||||
|
||||
much = PAGE_SIZE - (int)(paudio_buffer->pto -\
|
||||
paudio_buffer->pgo);
|
||||
if (much % 2)
|
||||
JOT(8, "MISTAKE? much is odd\n");
|
||||
|
||||
if (false == peasycap->microphone) {
|
||||
if (much > more)
|
||||
much = more;
|
||||
|
||||
memcpy(paudio_buffer->pto, p1, much);
|
||||
p1 += much;
|
||||
more -= much;
|
||||
} else {
|
||||
if (much > (2 * more))
|
||||
much = 2 * more;
|
||||
p2 = (__u8 *)paudio_buffer->pto;
|
||||
|
||||
for (j = 0; j < (much / 2); j++) {
|
||||
s16 = ((int) *p1) - 128;
|
||||
*p2 = (0xFF00 & s16) >> 8;
|
||||
*(p2 + 1) = (0x00FF & s16);
|
||||
p1++; p2 += 2;
|
||||
more--;
|
||||
}
|
||||
}
|
||||
(paudio_buffer->pto) += much;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JOT(12, "discarding audio samples because " \
|
||||
"%i=purb->iso_frame_desc[i].status\n", \
|
||||
purb->iso_frame_desc[i].status);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* RESUBMIT THIS URB AFTER NO ERROR
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (peasycap->audio_isoc_streaming) {
|
||||
rc = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (0 != rc) {
|
||||
SAY("ERROR: while %i=audio_idle, usb_submit_urb() failed " \
|
||||
"with rc:\n", peasycap->audio_idle);
|
||||
switch (rc) {
|
||||
case -ENOMEM: {
|
||||
SAY("ENOMEM\n"); break;
|
||||
}
|
||||
case -ENODEV: {
|
||||
SAY("ENODEV\n"); break;
|
||||
}
|
||||
case -ENXIO: {
|
||||
SAY("ENXIO\n"); break;
|
||||
}
|
||||
case -EINVAL: {
|
||||
SAY("EINVAL\n"); break;
|
||||
}
|
||||
case -EAGAIN: {
|
||||
SAY("EAGAIN\n"); break;
|
||||
}
|
||||
case -EFBIG: {
|
||||
SAY("EFBIG\n"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
SAY("EPIPE\n"); break;
|
||||
}
|
||||
case -EMSGSIZE: {
|
||||
SAY("EMSGSIZE\n"); break;
|
||||
}
|
||||
default: {
|
||||
SAY("0x%08X\n", rc); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO
|
||||
* STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT
|
||||
* HAVE AN IOCTL INTERFACE. THE VIDEO URBS, BY CONTRAST, MUST BE SUBMITTED
|
||||
* MUCH LATER: SEE COMMENTS IN FILE easycap_main.c.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
easysnd_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct usb_interface *pusb_interface;
|
||||
struct easycap *peasycap;
|
||||
int subminor, rc;
|
||||
|
||||
JOT(4, "begins.\n");
|
||||
|
||||
subminor = iminor(inode);
|
||||
|
||||
pusb_interface = usb_find_interface(&easycap_usb_driver, subminor);
|
||||
if (NULL == pusb_interface) {
|
||||
SAY("ERROR: pusb_interface is NULL\n");
|
||||
SAY("ending unsuccessfully\n");
|
||||
return -1;
|
||||
}
|
||||
peasycap = usb_get_intfdata(pusb_interface);
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL\n");
|
||||
SAY("ending unsuccessfully\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
file->private_data = peasycap;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* INITIALIZATION.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
JOT(4, "starting initialization\n");
|
||||
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
} else {
|
||||
JOT(16, "0x%08lX=peasycap->pusb_device\n", \
|
||||
(long int)peasycap->pusb_device);
|
||||
}
|
||||
|
||||
rc = audio_setup(peasycap);
|
||||
if (0 <= rc)
|
||||
JOT(8, "audio_setup() returned %i\n", rc);
|
||||
else
|
||||
JOT(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc);
|
||||
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device has become NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
rc = adjust_volume(peasycap, -8192);
|
||||
if (0 != rc) {
|
||||
SAY("ERROR: adjust_volume(default) returned %i\n", rc);
|
||||
return -EFAULT;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device has become NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \
|
||||
peasycap->audio_altsetting_on);
|
||||
JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \
|
||||
peasycap->audio_altsetting_on, rc);
|
||||
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device has become NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
rc = wakeup_device(peasycap->pusb_device);
|
||||
if (0 == rc)
|
||||
JOT(8, "wakeup_device() returned %i\n", rc);
|
||||
else
|
||||
JOT(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc);
|
||||
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device has become NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
submit_audio_urbs(peasycap);
|
||||
peasycap->audio_idle = 0;
|
||||
|
||||
peasycap->timeval1.tv_sec = 0;
|
||||
peasycap->timeval1.tv_usec = 0;
|
||||
|
||||
JOT(4, "finished initialization\n");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
int
|
||||
easysnd_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct easycap *peasycap;
|
||||
|
||||
JOT(4, "begins\n");
|
||||
|
||||
peasycap = (struct easycap *)file->private_data;
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR: peasycap is NULL.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (0 != kill_audio_urbs(peasycap)) {
|
||||
SAY("ERROR: kill_audio_urbs() failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
JOT(4, "ending successfully\n");
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
ssize_t
|
||||
easysnd_read(struct file *file, char __user *puserspacebuffer, \
|
||||
size_t kount, loff_t *poff)
|
||||
{
|
||||
struct timeval timeval;
|
||||
static struct timeval timeval1;
|
||||
static long long int audio_bytes, above, below, mean;
|
||||
struct signed_div_result sdr;
|
||||
unsigned char *p0;
|
||||
long int kount1, more, rc, l0, lm;
|
||||
int fragment;
|
||||
struct easycap *peasycap;
|
||||
struct data_buffer *pdata_buffer;
|
||||
size_t szret;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE.
|
||||
*
|
||||
******************************************************************************
|
||||
***** N.B. IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ******
|
||||
***** THIS CONDITION SIGNIFIES END-OF-FILE. ******
|
||||
******************************************************************************
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff));
|
||||
|
||||
peasycap = (struct easycap *)(file->private_data);
|
||||
if (NULL == peasycap) {
|
||||
SAY("ERROR in easysnd_read(): peasycap is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if ((0 > peasycap->audio_read) || \
|
||||
(audio_buffer_page_many <= peasycap->audio_read)) {
|
||||
SAY("ERROR: peasycap->audio_read out of range\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
|
||||
if ((struct data_buffer *)NULL == pdata_buffer) {
|
||||
SAY("ERROR: pdata_buffer is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
JOT(12, "before wait, %i=frag read %i=frag fill\n", \
|
||||
(peasycap->audio_read / audio_pages_per_fragment), \
|
||||
(peasycap->audio_fill / audio_pages_per_fragment));
|
||||
fragment = (peasycap->audio_read / audio_pages_per_fragment);
|
||||
while ((fragment == (peasycap->audio_fill / audio_pages_per_fragment)) || \
|
||||
(0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) {
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
JOT(16, "returning -EAGAIN as instructed\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
rc = wait_event_interruptible(peasycap->wq_audio, \
|
||||
(peasycap->audio_idle || peasycap->audio_eof || \
|
||||
((fragment != (peasycap->audio_fill / \
|
||||
audio_pages_per_fragment)) && \
|
||||
(0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo))))));
|
||||
if (0 != rc) {
|
||||
SAY("aborted by signal\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (peasycap->audio_eof) {
|
||||
JOT(8, "returning 0 because %i=audio_eof\n", \
|
||||
peasycap->audio_eof);
|
||||
kill_audio_urbs(peasycap);
|
||||
msleep(500);
|
||||
return 0;
|
||||
}
|
||||
if (peasycap->audio_idle) {
|
||||
JOT(16, "returning 0 because %i=audio_idle\n", \
|
||||
peasycap->audio_idle);
|
||||
return 0;
|
||||
}
|
||||
if (!peasycap->audio_isoc_streaming) {
|
||||
JOT(16, "returning 0 because audio urbs not streaming\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
JOT(12, "after wait, %i=frag read %i=frag fill\n", \
|
||||
(peasycap->audio_read / audio_pages_per_fragment), \
|
||||
(peasycap->audio_fill / audio_pages_per_fragment));
|
||||
szret = (size_t)0;
|
||||
while (fragment == (peasycap->audio_read / audio_pages_per_fragment)) {
|
||||
if (NULL == pdata_buffer->pgo) {
|
||||
SAY("ERROR: pdata_buffer->pgo is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == pdata_buffer->pto) {
|
||||
SAY("ERROR: pdata_buffer->pto is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
|
||||
if (0 > kount1) {
|
||||
SAY("easysnd_read: MISTAKE: kount1 is negative\n");
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
if (!kount1) {
|
||||
(peasycap->audio_read)++;
|
||||
if (audio_buffer_page_many <= peasycap->audio_read)
|
||||
peasycap->audio_read = 0;
|
||||
JOT(12, "bumped peasycap->audio_read to %i\n", \
|
||||
peasycap->audio_read);
|
||||
|
||||
if (fragment != (peasycap->audio_read / \
|
||||
audio_pages_per_fragment))
|
||||
break;
|
||||
|
||||
if ((0 > peasycap->audio_read) || \
|
||||
(audio_buffer_page_many <= peasycap->audio_read)) {
|
||||
SAY("ERROR: peasycap->audio_read out of range\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read];
|
||||
if ((struct data_buffer *)NULL == pdata_buffer) {
|
||||
SAY("ERROR: pdata_buffer is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == pdata_buffer->pgo) {
|
||||
SAY("ERROR: pdata_buffer->pgo is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (NULL == pdata_buffer->pto) {
|
||||
SAY("ERROR: pdata_buffer->pto is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo);
|
||||
}
|
||||
JOT(12, "ready to send %li bytes\n", (long int) kount1);
|
||||
JOT(12, "still to send %li bytes\n", (long int) kount);
|
||||
more = kount1;
|
||||
if (more > kount)
|
||||
more = kount;
|
||||
JOT(12, "agreed to send %li bytes from page %i\n", \
|
||||
more, peasycap->audio_read);
|
||||
if (!more)
|
||||
break;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* ACCUMULATE DYNAMIC-RANGE INFORMATION
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
p0 = (unsigned char *)pdata_buffer->pgo; l0 = 0; lm = more/2;
|
||||
while (l0 < lm) {
|
||||
SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \
|
||||
&peasycap->audio_square); l0++; p0 += 2;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more);
|
||||
if (0 != rc) {
|
||||
SAY("ERROR: copy_to_user() returned %li\n", rc);
|
||||
return -EFAULT;
|
||||
}
|
||||
*poff += (loff_t)more;
|
||||
szret += (size_t)more;
|
||||
pdata_buffer->pto += more;
|
||||
puserspacebuffer += more;
|
||||
kount -= (size_t)more;
|
||||
}
|
||||
JOT(12, "after read, %i=frag read %i=frag fill\n", \
|
||||
(peasycap->audio_read / audio_pages_per_fragment), \
|
||||
(peasycap->audio_fill / audio_pages_per_fragment));
|
||||
if (kount < 0) {
|
||||
SAY("MISTAKE: %li=kount %li=szret\n", \
|
||||
(long int)kount, (long int)szret);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
if (peasycap->audio_sample) {
|
||||
below = peasycap->audio_sample;
|
||||
above = peasycap->audio_square;
|
||||
sdr = signed_div(above, below);
|
||||
above = sdr.quotient;
|
||||
mean = peasycap->audio_niveau;
|
||||
sdr = signed_div(mean, peasycap->audio_sample);
|
||||
|
||||
JOT(12, "%8lli=mean %8lli=meansquare after %lli samples, =>\n", \
|
||||
sdr.quotient, above, peasycap->audio_sample);
|
||||
|
||||
sdr = signed_div(above, 32768);
|
||||
JOT(8, "audio dynamic range is roughly %lli\n", sdr.quotient);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* UPDATE THE AUDIO CLOCK
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
do_gettimeofday(&timeval);
|
||||
if (!peasycap->timeval1.tv_sec) {
|
||||
audio_bytes = 0;
|
||||
timeval1 = timeval;
|
||||
|
||||
if (mutex_lock_interruptible(&(peasycap->mutex_timeval1)))
|
||||
return -ERESTARTSYS;
|
||||
peasycap->timeval1 = timeval1;
|
||||
mutex_unlock(&(peasycap->mutex_timeval1));
|
||||
sdr.quotient = 192000;
|
||||
} else {
|
||||
audio_bytes += (long long int) szret;
|
||||
below = ((long long int)(1000000)) * \
|
||||
((long long int)(timeval.tv_sec - timeval1.tv_sec)) + \
|
||||
(long long int)(timeval.tv_usec - timeval1.tv_usec);
|
||||
above = 1000000 * ((long long int) audio_bytes);
|
||||
|
||||
if (below)
|
||||
sdr = signed_div(above, below);
|
||||
else
|
||||
sdr.quotient = 192000;
|
||||
}
|
||||
JOT(8, "audio streaming at %lli bytes/second\n", sdr.quotient);
|
||||
if (mutex_lock_interruptible(&(peasycap->mutex_timeval1)))
|
||||
return -ERESTARTSYS;
|
||||
peasycap->dnbydt = sdr.quotient;
|
||||
mutex_unlock(&(peasycap->mutex_timeval1));
|
||||
|
||||
JOT(8, "returning %li\n", (long int)szret);
|
||||
return szret;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* SUBMIT ALL AUDIO URBS.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
submit_audio_urbs(struct easycap *peasycap)
|
||||
{
|
||||
struct data_urb *pdata_urb;
|
||||
struct urb *purb;
|
||||
struct list_head *plist_head;
|
||||
int j, isbad, m, rc;
|
||||
int isbuf;
|
||||
|
||||
if ((struct list_head *)NULL == peasycap->purb_audio_head) {
|
||||
SAY("ERROR: peasycap->urb_audio_head uninitialized\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if ((struct usb_device *)NULL == peasycap->pusb_device) {
|
||||
SAY("ERROR: peasycap->pusb_device is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
if (!peasycap->audio_isoc_streaming) {
|
||||
JOT(4, "initial submission of all audio urbs\n");
|
||||
rc = usb_set_interface(peasycap->pusb_device,
|
||||
peasycap->audio_interface, \
|
||||
peasycap->audio_altsetting_on);
|
||||
JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", \
|
||||
peasycap->audio_interface, \
|
||||
peasycap->audio_altsetting_on, rc);
|
||||
|
||||
isbad = 0; m = 0;
|
||||
list_for_each(plist_head, (peasycap->purb_audio_head)) {
|
||||
pdata_urb = list_entry(plist_head, struct data_urb, list_head);
|
||||
if (NULL != pdata_urb) {
|
||||
purb = pdata_urb->purb;
|
||||
if (NULL != purb) {
|
||||
isbuf = pdata_urb->isbuf;
|
||||
|
||||
purb->interval = 1;
|
||||
purb->dev = peasycap->pusb_device;
|
||||
purb->pipe = \
|
||||
usb_rcvisocpipe(peasycap->pusb_device,\
|
||||
peasycap->audio_endpointnumber);
|
||||
purb->transfer_flags = URB_ISO_ASAP;
|
||||
purb->transfer_buffer = \
|
||||
peasycap->audio_isoc_buffer[isbuf].pgo;
|
||||
purb->transfer_buffer_length = \
|
||||
peasycap->audio_isoc_buffer_size;
|
||||
purb->complete = easysnd_complete;
|
||||
purb->context = peasycap;
|
||||
purb->start_frame = 0;
|
||||
purb->number_of_packets = \
|
||||
peasycap->audio_isoc_framesperdesc;
|
||||
for (j = 0; j < peasycap->\
|
||||
audio_isoc_framesperdesc; \
|
||||
j++) {
|
||||
purb->iso_frame_desc[j].offset = j * \
|
||||
peasycap->\
|
||||
audio_isoc_maxframesize;
|
||||
purb->iso_frame_desc[j].length = \
|
||||
peasycap->\
|
||||
audio_isoc_maxframesize;
|
||||
}
|
||||
|
||||
rc = usb_submit_urb(purb, GFP_KERNEL);
|
||||
if (0 != rc) {
|
||||
isbad++;
|
||||
SAY("ERROR: usb_submit_urb() failed" \
|
||||
" for urb with rc:\n");
|
||||
switch (rc) {
|
||||
case -ENOMEM: {
|
||||
SAY("ENOMEM\n"); break;
|
||||
}
|
||||
case -ENODEV: {
|
||||
SAY("ENODEV\n"); break;
|
||||
}
|
||||
case -ENXIO: {
|
||||
SAY("ENXIO\n"); break;
|
||||
}
|
||||
case -EINVAL: {
|
||||
SAY("EINVAL\n"); break;
|
||||
}
|
||||
case -EAGAIN: {
|
||||
SAY("EAGAIN\n"); break;
|
||||
}
|
||||
case -EFBIG: {
|
||||
SAY("EFBIG\n"); break;
|
||||
}
|
||||
case -EPIPE: {
|
||||
SAY("EPIPE\n"); break;
|
||||
}
|
||||
case -EMSGSIZE: {
|
||||
SAY("EMSGSIZE\n"); break;
|
||||
}
|
||||
default: {
|
||||
SAY("unknown error code %i\n",\
|
||||
rc); break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
m++;
|
||||
}
|
||||
} else {
|
||||
isbad++;
|
||||
}
|
||||
} else {
|
||||
isbad++;
|
||||
}
|
||||
}
|
||||
if (isbad) {
|
||||
JOT(4, "attempting cleanup instead of submitting\n");
|
||||
list_for_each(plist_head, (peasycap->purb_audio_head)) {
|
||||
pdata_urb = list_entry(plist_head, struct data_urb, \
|
||||
list_head);
|
||||
if (NULL != pdata_urb) {
|
||||
purb = pdata_urb->purb;
|
||||
if (NULL != purb)
|
||||
usb_kill_urb(purb);
|
||||
}
|
||||
}
|
||||
peasycap->audio_isoc_streaming = 0;
|
||||
} else {
|
||||
peasycap->audio_isoc_streaming = 1;
|
||||
JOT(4, "submitted %i audio urbs\n", m);
|
||||
}
|
||||
} else
|
||||
JOT(4, "already streaming audio urbs\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* KILL ALL AUDIO URBS.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
kill_audio_urbs(struct easycap *peasycap)
|
||||
{
|
||||
int m;
|
||||
struct list_head *plist_head;
|
||||
struct data_urb *pdata_urb;
|
||||
|
||||
if (peasycap->audio_isoc_streaming) {
|
||||
if ((struct list_head *)NULL != peasycap->purb_audio_head) {
|
||||
peasycap->audio_isoc_streaming = 0;
|
||||
JOT(4, "killing audio urbs\n");
|
||||
m = 0;
|
||||
list_for_each(plist_head, (peasycap->purb_audio_head)) {
|
||||
pdata_urb = list_entry(plist_head, struct data_urb,
|
||||
list_head);
|
||||
if ((struct data_urb *)NULL != pdata_urb) {
|
||||
if ((struct urb *)NULL != pdata_urb->purb) {
|
||||
usb_kill_urb(pdata_urb->purb);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
JOT(4, "%i audio urbs killed\n", m);
|
||||
} else {
|
||||
SAY("ERROR: peasycap->purb_audio_head is NULL\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
} else {
|
||||
JOT(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \
|
||||
peasycap->audio_isoc_streaming);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*****************************************************************************/
|
|
@ -0,0 +1,30 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* easycap_sound.h *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
extern struct easycap *peasycap;
|
||||
extern struct usb_driver easycap_usb_driver;
|
||||
extern unsigned int audio_buffer_page_many;
|
||||
extern unsigned int audio_pages_per_fragment;
|
|
@ -0,0 +1,27 @@
|
|||
/*****************************************************************************
|
||||
* *
|
||||
* easycap_standard.h *
|
||||
* *
|
||||
*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
extern struct easycap_standard easycap_standard[];
|
|
@ -0,0 +1,392 @@
|
|||
/******************************************************************************
|
||||
* *
|
||||
* easycap_testcard.c *
|
||||
* *
|
||||
******************************************************************************/
|
||||
/*
|
||||
*
|
||||
* Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
|
||||
*
|
||||
*
|
||||
* This 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.
|
||||
*
|
||||
* The software 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 software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "easycap.h"
|
||||
#include "easycap_debug.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
#define TESTCARD_BYTESPERLINE (2 * 1440)
|
||||
void
|
||||
easycap_testcard(struct easycap *peasycap, int field_fill)
|
||||
{
|
||||
int total;
|
||||
int y, u, v, r, g, b;
|
||||
unsigned char uyvy[4];
|
||||
|
||||
int i1, line, k, m, n, more, much, barwidth;
|
||||
unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2;
|
||||
struct data_buffer *pfield_buffer;
|
||||
|
||||
JOT(8, "%i=field_fill\n", field_fill);
|
||||
|
||||
if ((TESTCARD_BYTESPERLINE / 2) < peasycap->width) {
|
||||
SAY("ERROR: image is too wide\n");
|
||||
return;
|
||||
}
|
||||
if (peasycap->width % 16) {
|
||||
SAY("ERROR: indivisible image width\n");
|
||||
return;
|
||||
}
|
||||
|
||||
total = 0;
|
||||
barwidth = (2 * peasycap->width) / 8;
|
||||
|
||||
k = field_fill;
|
||||
m = 0;
|
||||
n = 0;
|
||||
|
||||
for (line = 0; line < (peasycap->height / 2); line++) {
|
||||
for (i1 = 0; i1 < 8; i1++) {
|
||||
r = (i1 * 256)/8;
|
||||
g = (i1 * 256)/8;
|
||||
b = (i1 * 256)/8;
|
||||
|
||||
y = 299*r/1000 + 587*g/1000 + 114*b/1000 ;
|
||||
u = -147*r/1000 - 289*g/1000 + 436*b/1000 ; u = u + 128;
|
||||
v = 615*r/1000 - 515*g/1000 - 100*b/1000 ; v = v + 128;
|
||||
|
||||
uyvy[0] = 0xFF & u ;
|
||||
uyvy[1] = 0xFF & y ;
|
||||
uyvy[2] = 0xFF & v ;
|
||||
uyvy[3] = 0xFF & y ;
|
||||
|
||||
p1 = &bfbar[0];
|
||||
while (p1 < &bfbar[barwidth]) {
|
||||
*p1++ = uyvy[0] ;
|
||||
*p1++ = uyvy[1] ;
|
||||
*p1++ = uyvy[2] ;
|
||||
*p1++ = uyvy[3] ;
|
||||
total += 4;
|
||||
}
|
||||
|
||||
p1 = &bfbar[0];
|
||||
more = barwidth;
|
||||
|
||||
while (more) {
|
||||
if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) {
|
||||
SAY("ERROR: bad m reached\n");
|
||||
return;
|
||||
}
|
||||
if (PAGE_SIZE < n) {
|
||||
SAY("ERROR: bad n reached\n"); return;
|
||||
}
|
||||
|
||||
if (0 > more) {
|
||||
SAY("ERROR: internal fault\n");
|
||||
return;
|
||||
}
|
||||
|
||||
much = PAGE_SIZE - n;
|
||||
if (much > more)
|
||||
much = more;
|
||||
pfield_buffer = &peasycap->field_buffer[k][m];
|
||||
p2 = pfield_buffer->pgo + n;
|
||||
memcpy(p2, p1, much);
|
||||
|
||||
p1 += much;
|
||||
n += much;
|
||||
more -= much;
|
||||
if (PAGE_SIZE == n) {
|
||||
m++;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JOT(8, "%i=total\n", total);
|
||||
if (total != peasycap->width * peasycap->height)
|
||||
SAY("ERROR: wrong number of bytes written: %i\n", total);
|
||||
return;
|
||||
}
|
||||
/*****************************************************************************/
|
||||
#if defined(EASYCAP_TESTTONE)
|
||||
/*-----------------------------------------------------------------------------
|
||||
THE tones[] ARRAY BELOW IS THE OUTPUT OF THIS PROGRAM,
|
||||
COMPILED gcc -o prog -lm prog.c
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
int main(void);
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i1, i2, last;
|
||||
double d1, d2;
|
||||
|
||||
last = 1024 - 1;
|
||||
d1 = 10.0*3.14159265/1024.0;
|
||||
printf("int tones[2048] =\n{\n");
|
||||
for (i1 = 0; i1 <= last; i1++)
|
||||
{
|
||||
d2 = ((double)i1) * d1;
|
||||
i2 = (int)(16384.0*sin(d2));
|
||||
|
||||
if (last != i1)
|
||||
{
|
||||
printf("%6i, ", i2); printf("%6i, ", i2);
|
||||
if (!((i1 + 1)%5)) printf("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%6i, ", i2); printf("%6i\n};\n", i2);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
-----------------------------------------------------------------------------*/
|
||||
int tones[2048] = {
|
||||
0, 0, 502, 502, 1004, 1004, 1505, 1505, 2005, 2005,
|
||||
2503, 2503, 2998, 2998, 3491, 3491, 3980, 3980, 4466, 4466,
|
||||
4948, 4948, 5424, 5424, 5896, 5896, 6362, 6362, 6822, 6822,
|
||||
7276, 7276, 7723, 7723, 8162, 8162, 8594, 8594, 9018, 9018,
|
||||
9434, 9434, 9840, 9840, 10237, 10237, 10625, 10625, 11002, 11002,
|
||||
11370, 11370, 11726, 11726, 12072, 12072, 12406, 12406, 12728, 12728,
|
||||
13038, 13038, 13337, 13337, 13622, 13622, 13895, 13895, 14155, 14155,
|
||||
14401, 14401, 14634, 14634, 14853, 14853, 15058, 15058, 15249, 15249,
|
||||
15426, 15426, 15588, 15588, 15735, 15735, 15868, 15868, 15985, 15985,
|
||||
16088, 16088, 16175, 16175, 16248, 16248, 16305, 16305, 16346, 16346,
|
||||
16372, 16372, 16383, 16383, 16379, 16379, 16359, 16359, 16323, 16323,
|
||||
16272, 16272, 16206, 16206, 16125, 16125, 16028, 16028, 15917, 15917,
|
||||
15790, 15790, 15649, 15649, 15492, 15492, 15322, 15322, 15136, 15136,
|
||||
14937, 14937, 14723, 14723, 14496, 14496, 14255, 14255, 14001, 14001,
|
||||
13733, 13733, 13452, 13452, 13159, 13159, 12854, 12854, 12536, 12536,
|
||||
12207, 12207, 11866, 11866, 11513, 11513, 11150, 11150, 10777, 10777,
|
||||
10393, 10393, 10000, 10000, 9597, 9597, 9185, 9185, 8765, 8765,
|
||||
8336, 8336, 7900, 7900, 7456, 7456, 7005, 7005, 6547, 6547,
|
||||
6083, 6083, 5614, 5614, 5139, 5139, 4659, 4659, 4175, 4175,
|
||||
3687, 3687, 3196, 3196, 2701, 2701, 2204, 2204, 1705, 1705,
|
||||
1205, 1205, 703, 703, 201, 201, -301, -301, -803, -803,
|
||||
-1305, -1305, -1805, -1805, -2304, -2304, -2801, -2801, -3294, -3294,
|
||||
-3785, -3785, -4272, -4272, -4756, -4756, -5234, -5234, -5708, -5708,
|
||||
-6176, -6176, -6639, -6639, -7095, -7095, -7545, -7545, -7988, -7988,
|
||||
-8423, -8423, -8850, -8850, -9268, -9268, -9679, -9679, -10079, -10079,
|
||||
-10471, -10471, -10853, -10853, -11224, -11224, -11585, -11585, -11935, -11935,
|
||||
-12273, -12273, -12600, -12600, -12916, -12916, -13219, -13219, -13510, -13510,
|
||||
-13788, -13788, -14053, -14053, -14304, -14304, -14543, -14543, -14767, -14767,
|
||||
-14978, -14978, -15175, -15175, -15357, -15357, -15525, -15525, -15678, -15678,
|
||||
-15817, -15817, -15940, -15940, -16049, -16049, -16142, -16142, -16221, -16221,
|
||||
-16284, -16284, -16331, -16331, -16364, -16364, -16381, -16381, -16382, -16382,
|
||||
-16368, -16368, -16339, -16339, -16294, -16294, -16234, -16234, -16159, -16159,
|
||||
-16069, -16069, -15963, -15963, -15842, -15842, -15707, -15707, -15557, -15557,
|
||||
-15392, -15392, -15212, -15212, -15018, -15018, -14810, -14810, -14589, -14589,
|
||||
-14353, -14353, -14104, -14104, -13842, -13842, -13566, -13566, -13278, -13278,
|
||||
-12977, -12977, -12665, -12665, -12340, -12340, -12003, -12003, -11656, -11656,
|
||||
-11297, -11297, -10928, -10928, -10548, -10548, -10159, -10159, -9759, -9759,
|
||||
-9351, -9351, -8934, -8934, -8509, -8509, -8075, -8075, -7634, -7634,
|
||||
-7186, -7186, -6731, -6731, -6269, -6269, -5802, -5802, -5329, -5329,
|
||||
-4852, -4852, -4369, -4369, -3883, -3883, -3393, -3393, -2900, -2900,
|
||||
-2404, -2404, -1905, -1905, -1405, -1405, -904, -904, -402, -402,
|
||||
100, 100, 603, 603, 1105, 1105, 1605, 1605, 2105, 2105,
|
||||
2602, 2602, 3097, 3097, 3589, 3589, 4078, 4078, 4563, 4563,
|
||||
5043, 5043, 5519, 5519, 5990, 5990, 6455, 6455, 6914, 6914,
|
||||
7366, 7366, 7811, 7811, 8249, 8249, 8680, 8680, 9102, 9102,
|
||||
9516, 9516, 9920, 9920, 10315, 10315, 10701, 10701, 11077, 11077,
|
||||
11442, 11442, 11796, 11796, 12139, 12139, 12471, 12471, 12791, 12791,
|
||||
13099, 13099, 13395, 13395, 13678, 13678, 13948, 13948, 14205, 14205,
|
||||
14449, 14449, 14679, 14679, 14895, 14895, 15098, 15098, 15286, 15286,
|
||||
15459, 15459, 15618, 15618, 15763, 15763, 15892, 15892, 16007, 16007,
|
||||
16107, 16107, 16191, 16191, 16260, 16260, 16314, 16314, 16353, 16353,
|
||||
16376, 16376, 16384, 16384, 16376, 16376, 16353, 16353, 16314, 16314,
|
||||
16260, 16260, 16191, 16191, 16107, 16107, 16007, 16007, 15892, 15892,
|
||||
15763, 15763, 15618, 15618, 15459, 15459, 15286, 15286, 15098, 15098,
|
||||
14895, 14895, 14679, 14679, 14449, 14449, 14205, 14205, 13948, 13948,
|
||||
13678, 13678, 13395, 13395, 13099, 13099, 12791, 12791, 12471, 12471,
|
||||
12139, 12139, 11796, 11796, 11442, 11442, 11077, 11077, 10701, 10701,
|
||||
10315, 10315, 9920, 9920, 9516, 9516, 9102, 9102, 8680, 8680,
|
||||
8249, 8249, 7811, 7811, 7366, 7366, 6914, 6914, 6455, 6455,
|
||||
5990, 5990, 5519, 5519, 5043, 5043, 4563, 4563, 4078, 4078,
|
||||
3589, 3589, 3097, 3097, 2602, 2602, 2105, 2105, 1605, 1605,
|
||||
1105, 1105, 603, 603, 100, 100, -402, -402, -904, -904,
|
||||
-1405, -1405, -1905, -1905, -2404, -2404, -2900, -2900, -3393, -3393,
|
||||
-3883, -3883, -4369, -4369, -4852, -4852, -5329, -5329, -5802, -5802,
|
||||
-6269, -6269, -6731, -6731, -7186, -7186, -7634, -7634, -8075, -8075,
|
||||
-8509, -8509, -8934, -8934, -9351, -9351, -9759, -9759, -10159, -10159,
|
||||
-10548, -10548, -10928, -10928, -11297, -11297, -11656, -11656, -12003, -12003,
|
||||
-12340, -12340, -12665, -12665, -12977, -12977, -13278, -13278, -13566, -13566,
|
||||
-13842, -13842, -14104, -14104, -14353, -14353, -14589, -14589, -14810, -14810,
|
||||
-15018, -15018, -15212, -15212, -15392, -15392, -15557, -15557, -15707, -15707,
|
||||
-15842, -15842, -15963, -15963, -16069, -16069, -16159, -16159, -16234, -16234,
|
||||
-16294, -16294, -16339, -16339, -16368, -16368, -16382, -16382, -16381, -16381,
|
||||
-16364, -16364, -16331, -16331, -16284, -16284, -16221, -16221, -16142, -16142,
|
||||
-16049, -16049, -15940, -15940, -15817, -15817, -15678, -15678, -15525, -15525,
|
||||
-15357, -15357, -15175, -15175, -14978, -14978, -14767, -14767, -14543, -14543,
|
||||
-14304, -14304, -14053, -14053, -13788, -13788, -13510, -13510, -13219, -13219,
|
||||
-12916, -12916, -12600, -12600, -12273, -12273, -11935, -11935, -11585, -11585,
|
||||
-11224, -11224, -10853, -10853, -10471, -10471, -10079, -10079, -9679, -9679,
|
||||
-9268, -9268, -8850, -8850, -8423, -8423, -7988, -7988, -7545, -7545,
|
||||
-7095, -7095, -6639, -6639, -6176, -6176, -5708, -5708, -5234, -5234,
|
||||
-4756, -4756, -4272, -4272, -3785, -3785, -3294, -3294, -2801, -2801,
|
||||
-2304, -2304, -1805, -1805, -1305, -1305, -803, -803, -301, -301,
|
||||
201, 201, 703, 703, 1205, 1205, 1705, 1705, 2204, 2204,
|
||||
2701, 2701, 3196, 3196, 3687, 3687, 4175, 4175, 4659, 4659,
|
||||
5139, 5139, 5614, 5614, 6083, 6083, 6547, 6547, 7005, 7005,
|
||||
7456, 7456, 7900, 7900, 8336, 8336, 8765, 8765, 9185, 9185,
|
||||
9597, 9597, 10000, 10000, 10393, 10393, 10777, 10777, 11150, 11150,
|
||||
11513, 11513, 11866, 11866, 12207, 12207, 12536, 12536, 12854, 12854,
|
||||
13159, 13159, 13452, 13452, 13733, 13733, 14001, 14001, 14255, 14255,
|
||||
14496, 14496, 14723, 14723, 14937, 14937, 15136, 15136, 15322, 15322,
|
||||
15492, 15492, 15649, 15649, 15790, 15790, 15917, 15917, 16028, 16028,
|
||||
16125, 16125, 16206, 16206, 16272, 16272, 16323, 16323, 16359, 16359,
|
||||
16379, 16379, 16383, 16383, 16372, 16372, 16346, 16346, 16305, 16305,
|
||||
16248, 16248, 16175, 16175, 16088, 16088, 15985, 15985, 15868, 15868,
|
||||
15735, 15735, 15588, 15588, 15426, 15426, 15249, 15249, 15058, 15058,
|
||||
14853, 14853, 14634, 14634, 14401, 14401, 14155, 14155, 13895, 13895,
|
||||
13622, 13622, 13337, 13337, 13038, 13038, 12728, 12728, 12406, 12406,
|
||||
12072, 12072, 11726, 11726, 11370, 11370, 11002, 11002, 10625, 10625,
|
||||
10237, 10237, 9840, 9840, 9434, 9434, 9018, 9018, 8594, 8594,
|
||||
8162, 8162, 7723, 7723, 7276, 7276, 6822, 6822, 6362, 6362,
|
||||
5896, 5896, 5424, 5424, 4948, 4948, 4466, 4466, 3980, 3980,
|
||||
3491, 3491, 2998, 2998, 2503, 2503, 2005, 2005, 1505, 1505,
|
||||
1004, 1004, 502, 502, 0, 0, -502, -502, -1004, -1004,
|
||||
-1505, -1505, -2005, -2005, -2503, -2503, -2998, -2998, -3491, -3491,
|
||||
-3980, -3980, -4466, -4466, -4948, -4948, -5424, -5424, -5896, -5896,
|
||||
-6362, -6362, -6822, -6822, -7276, -7276, -7723, -7723, -8162, -8162,
|
||||
-8594, -8594, -9018, -9018, -9434, -9434, -9840, -9840, -10237, -10237,
|
||||
-10625, -10625, -11002, -11002, -11370, -11370, -11726, -11726, -12072, -12072,
|
||||
-12406, -12406, -12728, -12728, -13038, -13038, -13337, -13337, -13622, -13622,
|
||||
-13895, -13895, -14155, -14155, -14401, -14401, -14634, -14634, -14853, -14853,
|
||||
-15058, -15058, -15249, -15249, -15426, -15426, -15588, -15588, -15735, -15735,
|
||||
-15868, -15868, -15985, -15985, -16088, -16088, -16175, -16175, -16248, -16248,
|
||||
-16305, -16305, -16346, -16346, -16372, -16372, -16383, -16383, -16379, -16379,
|
||||
-16359, -16359, -16323, -16323, -16272, -16272, -16206, -16206, -16125, -16125,
|
||||
-16028, -16028, -15917, -15917, -15790, -15790, -15649, -15649, -15492, -15492,
|
||||
-15322, -15322, -15136, -15136, -14937, -14937, -14723, -14723, -14496, -14496,
|
||||
-14255, -14255, -14001, -14001, -13733, -13733, -13452, -13452, -13159, -13159,
|
||||
-12854, -12854, -12536, -12536, -12207, -12207, -11866, -11866, -11513, -11513,
|
||||
-11150, -11150, -10777, -10777, -10393, -10393, -10000, -10000, -9597, -9597,
|
||||
-9185, -9185, -8765, -8765, -8336, -8336, -7900, -7900, -7456, -7456,
|
||||
-7005, -7005, -6547, -6547, -6083, -6083, -5614, -5614, -5139, -5139,
|
||||
-4659, -4659, -4175, -4175, -3687, -3687, -3196, -3196, -2701, -2701,
|
||||
-2204, -2204, -1705, -1705, -1205, -1205, -703, -703, -201, -201,
|
||||
301, 301, 803, 803, 1305, 1305, 1805, 1805, 2304, 2304,
|
||||
2801, 2801, 3294, 3294, 3785, 3785, 4272, 4272, 4756, 4756,
|
||||
5234, 5234, 5708, 5708, 6176, 6176, 6639, 6639, 7095, 7095,
|
||||
7545, 7545, 7988, 7988, 8423, 8423, 8850, 8850, 9268, 9268,
|
||||
9679, 9679, 10079, 10079, 10471, 10471, 10853, 10853, 11224, 11224,
|
||||
11585, 11585, 11935, 11935, 12273, 12273, 12600, 12600, 12916, 12916,
|
||||
13219, 13219, 13510, 13510, 13788, 13788, 14053, 14053, 14304, 14304,
|
||||
14543, 14543, 14767, 14767, 14978, 14978, 15175, 15175, 15357, 15357,
|
||||
15525, 15525, 15678, 15678, 15817, 15817, 15940, 15940, 16049, 16049,
|
||||
16142, 16142, 16221, 16221, 16284, 16284, 16331, 16331, 16364, 16364,
|
||||
16381, 16381, 16382, 16382, 16368, 16368, 16339, 16339, 16294, 16294,
|
||||
16234, 16234, 16159, 16159, 16069, 16069, 15963, 15963, 15842, 15842,
|
||||
15707, 15707, 15557, 15557, 15392, 15392, 15212, 15212, 15018, 15018,
|
||||
14810, 14810, 14589, 14589, 14353, 14353, 14104, 14104, 13842, 13842,
|
||||
13566, 13566, 13278, 13278, 12977, 12977, 12665, 12665, 12340, 12340,
|
||||
12003, 12003, 11656, 11656, 11297, 11297, 10928, 10928, 10548, 10548,
|
||||
10159, 10159, 9759, 9759, 9351, 9351, 8934, 8934, 8509, 8509,
|
||||
8075, 8075, 7634, 7634, 7186, 7186, 6731, 6731, 6269, 6269,
|
||||
5802, 5802, 5329, 5329, 4852, 4852, 4369, 4369, 3883, 3883,
|
||||
3393, 3393, 2900, 2900, 2404, 2404, 1905, 1905, 1405, 1405,
|
||||
904, 904, 402, 402, -100, -100, -603, -603, -1105, -1105,
|
||||
-1605, -1605, -2105, -2105, -2602, -2602, -3097, -3097, -3589, -3589,
|
||||
-4078, -4078, -4563, -4563, -5043, -5043, -5519, -5519, -5990, -5990,
|
||||
-6455, -6455, -6914, -6914, -7366, -7366, -7811, -7811, -8249, -8249,
|
||||
-8680, -8680, -9102, -9102, -9516, -9516, -9920, -9920, -10315, -10315,
|
||||
-10701, -10701, -11077, -11077, -11442, -11442, -11796, -11796, -12139, -12139,
|
||||
-12471, -12471, -12791, -12791, -13099, -13099, -13395, -13395, -13678, -13678,
|
||||
-13948, -13948, -14205, -14205, -14449, -14449, -14679, -14679, -14895, -14895,
|
||||
-15098, -15098, -15286, -15286, -15459, -15459, -15618, -15618, -15763, -15763,
|
||||
-15892, -15892, -16007, -16007, -16107, -16107, -16191, -16191, -16260, -16260,
|
||||
-16314, -16314, -16353, -16353, -16376, -16376, -16383, -16383, -16376, -16376,
|
||||
-16353, -16353, -16314, -16314, -16260, -16260, -16191, -16191, -16107, -16107,
|
||||
-16007, -16007, -15892, -15892, -15763, -15763, -15618, -15618, -15459, -15459,
|
||||
-15286, -15286, -15098, -15098, -14895, -14895, -14679, -14679, -14449, -14449,
|
||||
-14205, -14205, -13948, -13948, -13678, -13678, -13395, -13395, -13099, -13099,
|
||||
-12791, -12791, -12471, -12471, -12139, -12139, -11796, -11796, -11442, -11442,
|
||||
-11077, -11077, -10701, -10701, -10315, -10315, -9920, -9920, -9516, -9516,
|
||||
-9102, -9102, -8680, -8680, -8249, -8249, -7811, -7811, -7366, -7366,
|
||||
-6914, -6914, -6455, -6455, -5990, -5990, -5519, -5519, -5043, -5043,
|
||||
-4563, -4563, -4078, -4078, -3589, -3589, -3097, -3097, -2602, -2602,
|
||||
-2105, -2105, -1605, -1605, -1105, -1105, -603, -603, -100, -100,
|
||||
402, 402, 904, 904, 1405, 1405, 1905, 1905, 2404, 2404,
|
||||
2900, 2900, 3393, 3393, 3883, 3883, 4369, 4369, 4852, 4852,
|
||||
5329, 5329, 5802, 5802, 6269, 6269, 6731, 6731, 7186, 7186,
|
||||
7634, 7634, 8075, 8075, 8509, 8509, 8934, 8934, 9351, 9351,
|
||||
9759, 9759, 10159, 10159, 10548, 10548, 10928, 10928, 11297, 11297,
|
||||
11656, 11656, 12003, 12003, 12340, 12340, 12665, 12665, 12977, 12977,
|
||||
13278, 13278, 13566, 13566, 13842, 13842, 14104, 14104, 14353, 14353,
|
||||
14589, 14589, 14810, 14810, 15018, 15018, 15212, 15212, 15392, 15392,
|
||||
15557, 15557, 15707, 15707, 15842, 15842, 15963, 15963, 16069, 16069,
|
||||
16159, 16159, 16234, 16234, 16294, 16294, 16339, 16339, 16368, 16368,
|
||||
16382, 16382, 16381, 16381, 16364, 16364, 16331, 16331, 16284, 16284,
|
||||
16221, 16221, 16142, 16142, 16049, 16049, 15940, 15940, 15817, 15817,
|
||||
15678, 15678, 15525, 15525, 15357, 15357, 15175, 15175, 14978, 14978,
|
||||
14767, 14767, 14543, 14543, 14304, 14304, 14053, 14053, 13788, 13788,
|
||||
13510, 13510, 13219, 13219, 12916, 12916, 12600, 12600, 12273, 12273,
|
||||
11935, 11935, 11585, 11585, 11224, 11224, 10853, 10853, 10471, 10471,
|
||||
10079, 10079, 9679, 9679, 9268, 9268, 8850, 8850, 8423, 8423,
|
||||
7988, 7988, 7545, 7545, 7095, 7095, 6639, 6639, 6176, 6176,
|
||||
5708, 5708, 5234, 5234, 4756, 4756, 4272, 4272, 3785, 3785,
|
||||
3294, 3294, 2801, 2801, 2304, 2304, 1805, 1805, 1305, 1305,
|
||||
803, 803, 301, 301, -201, -201, -703, -703, -1205, -1205,
|
||||
-1705, -1705, -2204, -2204, -2701, -2701, -3196, -3196, -3687, -3687,
|
||||
-4175, -4175, -4659, -4659, -5139, -5139, -5614, -5614, -6083, -6083,
|
||||
-6547, -6547, -7005, -7005, -7456, -7456, -7900, -7900, -8336, -8336,
|
||||
-8765, -8765, -9185, -9185, -9597, -9597, -10000, -10000, -10393, -10393,
|
||||
-10777, -10777, -11150, -11150, -11513, -11513, -11866, -11866, -12207, -12207,
|
||||
-12536, -12536, -12854, -12854, -13159, -13159, -13452, -13452, -13733, -13733,
|
||||
-14001, -14001, -14255, -14255, -14496, -14496, -14723, -14723, -14937, -14937,
|
||||
-15136, -15136, -15322, -15322, -15492, -15492, -15649, -15649, -15790, -15790,
|
||||
-15917, -15917, -16028, -16028, -16125, -16125, -16206, -16206, -16272, -16272,
|
||||
-16323, -16323, -16359, -16359, -16379, -16379, -16383, -16383, -16372, -16372,
|
||||
-16346, -16346, -16305, -16305, -16248, -16248, -16175, -16175, -16088, -16088,
|
||||
-15985, -15985, -15868, -15868, -15735, -15735, -15588, -15588, -15426, -15426,
|
||||
-15249, -15249, -15058, -15058, -14853, -14853, -14634, -14634, -14401, -14401,
|
||||
-14155, -14155, -13895, -13895, -13622, -13622, -13337, -13337, -13038, -13038,
|
||||
-12728, -12728, -12406, -12406, -12072, -12072, -11726, -11726, -11370, -11370,
|
||||
-11002, -11002, -10625, -10625, -10237, -10237, -9840, -9840, -9434, -9434,
|
||||
-9018, -9018, -8594, -8594, -8162, -8162, -7723, -7723, -7276, -7276,
|
||||
-6822, -6822, -6362, -6362, -5896, -5896, -5424, -5424, -4948, -4948,
|
||||
-4466, -4466, -3980, -3980, -3491, -3491, -2998, -2998, -2503, -2503,
|
||||
-2005, -2005, -1505, -1505, -1004, -1004, -502, -502
|
||||
};
|
||||
/*****************************************************************************/
|
||||
void
|
||||
easysnd_testtone(struct easycap *peasycap, int audio_fill)
|
||||
{
|
||||
int i1;
|
||||
unsigned char *p2;
|
||||
struct data_buffer *paudio_buffer;
|
||||
|
||||
JOT(8, "%i=audio_fill\n", audio_fill);
|
||||
|
||||
paudio_buffer = &peasycap->audio_buffer[audio_fill];
|
||||
|
||||
p2 = (unsigned char *)(paudio_buffer->pgo);
|
||||
for (i1 = 0; i1 < PAGE_SIZE; i1 += 4, p2 += 4) {
|
||||
*p2 = (unsigned char) (0x00FF & tones[i1/2]);
|
||||
*(p2 + 1) = (unsigned char)((0xFF00 & tones[i1/2]) >> 8);
|
||||
*(p2 + 2) = (unsigned char) (0x00FF & tones[i1/2 + 1]);
|
||||
*(p2 + 3) = (unsigned char)((0xFF00 & tones[i1/2 + 1]) >> 8);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /*EASYCAP_TESTTONE*/
|
||||
/*****************************************************************************/
|
Загрузка…
Ссылка в новой задаче