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:
R.M. Thomas 2010-06-18 12:29:49 -07:00 committed by Greg Kroah-Hartman
parent 178f16db8f
commit 702422bd2d
16 changed files with 10811 additions and 0 deletions

View File

@ -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

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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*/

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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
}
};
/*****************************************************************************/

View File

@ -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;
}
/*****************************************************************************/

View File

@ -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;

View File

@ -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[];

View File

@ -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*/
/*****************************************************************************/