/***************************************************************************** * * * easycap.h * * * *****************************************************************************/ /* * * Copyright (C) 2010 R.M. Thomas * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) #include #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ #if (!defined(__OLD_VIDIOC_)) #define __OLD_VIDIOC_ #endif /* !defined(__OLD_VIDIOC_) */ #include #include #if defined(EASYCAP_NEEDS_USBVIDEO_H) #include #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.21" #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 /*---------------------------------------------------------------------------*/ /* * 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) /*---------------------------------------------------------------------------*/ /* * 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; }; /*---------------------------------------------------------------------------*/ struct easycap_standard { __u16 mask; struct v4l2_standard v4l2_standard; }; struct easycap_format { __u16 mask; char name[128]; struct v4l2_format v4l2_format; }; /*---------------------------------------------------------------------------*/ /* * 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 { unsigned int audio_pages_per_fragment; unsigned int audio_bytes_per_fragment; unsigned int audio_buffer_page_many; #define UPSAMPLE #if defined(UPSAMPLE) __s16 oldaudio; #endif /*UPSAMPLE*/ struct easycap_format easycap_format[1 + SETTINGS_MANY]; 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[]; }; /*---------------------------------------------------------------------------*/ /* * VIDEO FUNCTION PROTOTYPES */ /*---------------------------------------------------------------------------*/ void easycap_complete(struct urb *); int easycap_open(struct inode *, struct file *); int easycap_release(struct inode *, struct file *); long easycap_ioctl(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 *); 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 *); long easysnd_ioctl(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); /*---------------------------------------------------------------------------*/ /* * 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*/