Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

R.M. Thomas and committed by
Greg Kroah-Hartman
702422bd 178f16db

+10811
+2
drivers/staging/Kconfig
··· 149 149 150 150 source "drivers/staging/msm/Kconfig" 151 151 152 + source "drivers/staging/easycap/Kconfig" 153 + 152 154 endif # !STAGING_EXCLUDE_BUILD 153 155 endif # STAGING
+1
drivers/staging/Makefile
··· 55 55 obj-$(CONFIG_FB_XGI) += xgifb/ 56 56 obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ 57 57 obj-$(CONFIG_MSM_STAGING) += msm/ 58 + obj-$(CONFIG_EASYCAP) += easycap/
+16
drivers/staging/easycap/Kconfig
··· 1 + config EASYCAP 2 + tristate "EasyCAP USB ID 05e1:0408 support" 3 + 4 + ---help--- 5 + This is an integrated audio/video driver for EasyCAP cards with 6 + USB ID 05e1:0408. It supports two hardware variants: 7 + 8 + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, 9 + having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) 10 + 11 + * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled 12 + 1, 2, 3, 4 and an unlabelled input cable for a microphone. 13 + 14 + To compile this driver as a module, choose M here: the 15 + module will be called easycap 16 +
+13
drivers/staging/easycap/Makefile
··· 1 + 2 + obj-$(CONFIG_EASYCAP) += easycap.o 3 + 4 + easycap-objs := easycap_main.o easycap_low.o easycap_sound.o 5 + easycap-objs += easycap_ioctl.o easycap_settings.o 6 + easycap-objs += easycap_testcard.o 7 + 8 + EXTRA_CFLAGS += -Wall 9 + # Impose all or none of the following: 10 + EXTRA_CFLAGS += -DEASYCAP_IS_VIDEODEV_CLIENT 11 + EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_DEVICE_H 12 + EXTRA_CFLAGS += -DEASYCAP_NEEDS_V4L2_FOPS 13 +
+130
drivers/staging/easycap/README
··· 1 + 2 + *********************************************************** 3 + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60 * 4 + * and * 5 + * EasyCAP002 4-Channel USB 2.0 DVR * 6 + *********************************************************** 7 + Mike Thomas <rmthomas@sciolus.org> 8 + 9 + 10 + 11 + SUPPORTED HARDWARE 12 + ------------------ 13 + 14 + This driver is intended for use with hardware having USB ID 05e1:0408. 15 + Two kinds of EasyCAP have this USB ID, namely: 16 + 17 + * EasyCAP USB 2.0 Video Adapter with Audio, Model DC60, 18 + having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R) 19 + 20 + * EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled 21 + 1, 2, 3, 4 and an unlabelled input cable for a microphone. 22 + 23 + 24 + BUILD OPTIONS AND DEPENDENCIES 25 + ------------------------------ 26 + 27 + If the parameter EASYCAP_IS_VIDEODEV_CLIENT is undefined during compilation 28 + the built module is entirely independent of the videodev module, and when 29 + the EasyCAP is physically plugged into a USB port the special files 30 + /dev/easycap0 and /dev/easysnd1 are created as video and sound sources 31 + respectively. 32 + 33 + If the parameter EASYCAP_IS_VIDEODEV_CLIENT is defined during compilation 34 + the built easycap module is configured to register with the videodev module, 35 + in which case the special files created when the EasyCAP is plugged in are 36 + /dev/video0 and /dev/easysnd0. Use of the easycap module as a client of 37 + the videodev module has received very little testing as of June 2010. 38 + 39 + 40 + KNOWN BUILD PROBLEMS 41 + -------------------- 42 + 43 + (1) Recent gcc versions may generate the message: 44 + 45 + warning: the frame size of .... bytes is larger than 1024 bytes 46 + 47 + This warning can be suppressed by specifying in the Makefile: 48 + 49 + EXTRA_CFLAGS += -Wframe-larger-than=8192 50 + 51 + but it would be preferable to remove the cause of the warning. 52 + 53 + 54 + KNOWN RUNTIME ISSUES 55 + -------------------- 56 + 57 + (1) Randomly (maybe 5 to 10% of occasions) the driver fails to produce any 58 + output at start-up. Closing mplayer (or whatever the user program is) and 59 + restarting it restores normal performance without any other remedial action 60 + being necessary. The reason for this is not known. 61 + 62 + (2) Intentionally, this driver will not stream material which is unambiguously 63 + identified by the hardware as copy-protected. The video output will freeze 64 + within about a minute when this situation arises. 65 + 66 + (3) The controls for luminance, contrast, saturation, hue and volume may not 67 + always work properly. 68 + 69 + (4) Reduced-resolution S-Video seems to suffer from moire artefacts. No 70 + attempt has yet been made to rememdy this. 71 + 72 + 73 + SUPPORTED TV STANDARDS AND RESOLUTIONS 74 + -------------------------------------- 75 + 76 + The following TV standards are natively supported by the hardware and are 77 + usable as (for example) the "norm=" parameter in the mplayer command: 78 + 79 + PAL_BGHIN, NTSC_N_443, 80 + PAL_Nc, NTSC_N, 81 + SECAM, NTSC_M, NTSC_M_JP, 82 + PAL_60, NTSC_443, 83 + PAL_M. 84 + 85 + The available picture sizes are: 86 + 87 + at 25 frames per second: 720x576, 704x576, 640x480, 360x288, 320x240; 88 + at 30 frames per second: 720x480, 640x480, 360x240, 320x240; 89 + 90 + 91 + WHAT'S TESTED AND WHAT'S NOT 92 + ---------------------------- 93 + 94 + This driver is known to work with mplayer, mencoder, tvtime and sufficiently 95 + recent versions of vlc. An interface to ffmpeg is implemented, but serious 96 + audio-video synchronization problems remain. 97 + 98 + The driver is designed to support all the TV standards accepted by the 99 + hardware, but as yet it has actually been tested on only a few of these. 100 + 101 + I have been unable to test and calibrate the S-video input myself because I 102 + do not possess any equipment with S-video output. 103 + 104 + This driver does not understand the V4L1 IOCTL commands, so programs such 105 + as camorama are not compatible. There are reports that the driver does 106 + work with sufficiently recent (V4L2) versions of zoneminder, but I have not 107 + attempted to confirm this myself. 108 + 109 + 110 + UDEV RULES 111 + ---------- 112 + 113 + In order that the special files /dev/easycap0 and /dev/easysnd1 are created 114 + with conveniently relaxed permissions when the EasyCAP is plugged in, a file 115 + is preferably to be provided in directory /etc/udev/rules.d with content: 116 + 117 + ACTION!="add|change", GOTO="easycap_rules_end" 118 + ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \ 119 + MODE="0666", OWNER="root", GROUP="root" 120 + LABEL="easycap_rules_end" 121 + 122 + 123 + ACKNOWLEGEMENTS AND REFERENCES 124 + ------------------------------ 125 + This driver makes use of information contained in the Syntek Semicon DC-1125 126 + Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/ 127 + by Nicolas Vivien. Particularly useful has been a patch to the latter driver 128 + provided by Ivor Hewitt in January 2009. The NTSC implementation is taken 129 + from the work of Ben Trask. 130 +
+632
drivers/staging/easycap/easycap.h
··· 1 + /***************************************************************************** 2 + * * 3 + * easycap.h * 4 + * * 5 + *****************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + /*---------------------------------------------------------------------------*/ 28 + /* 29 + * THE FOLLOWING PARAMETERS ARE UNDEFINED: 30 + * 31 + * EASYCAP_DEBUG 32 + * EASYCAP_IS_VIDEODEV_CLIENT 33 + * EASYCAP_NEEDS_USBVIDEO_H 34 + * EASYCAP_NEEDS_V4L2_DEVICE_H 35 + * EASYCAP_NEEDS_V4L2_FOPS 36 + * 37 + * IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER 38 + * OPTIONS. 39 + */ 40 + /*---------------------------------------------------------------------------*/ 41 + 42 + #if (!defined(EASYCAP_H)) 43 + #define EASYCAP_H 44 + 45 + #if defined(EASYCAP_DEBUG) 46 + #if (9 < EASYCAP_DEBUG) 47 + #error Debug levels 0 to 9 are okay.\ 48 + To achieve higher levels, remove this trap manually from easycap.h 49 + #endif 50 + #endif /*EASYCAP_DEBUG*/ 51 + /*---------------------------------------------------------------------------*/ 52 + /* 53 + * THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED: 54 + */ 55 + /*---------------------------------------------------------------------------*/ 56 + #undef PREFER_NTSC 57 + #undef EASYCAP_TESTCARD 58 + #undef EASYCAP_TESTTONE 59 + #undef LOCKFRAME 60 + #undef NOREADBACK 61 + #undef AUDIOTIME 62 + /*---------------------------------------------------------------------------*/ 63 + /* 64 + * 65 + * DEFINE BRIDGER TO ACTIVATE THE ROUTINE FOR BRIDGING VIDEOTAPE DROPOUTS. 66 + * 67 + * *** UNDER DEVELOPMENT/TESTING - NOT READY YET!*** 68 + * 69 + */ 70 + /*---------------------------------------------------------------------------*/ 71 + #undef BRIDGER 72 + /*---------------------------------------------------------------------------*/ 73 + 74 + #include <linux/kernel.h> 75 + #include <linux/errno.h> 76 + #include <linux/init.h> 77 + #include <linux/slab.h> 78 + #include <linux/module.h> 79 + #include <linux/kref.h> 80 + #include <linux/smp_lock.h> 81 + #include <linux/usb.h> 82 + #include <linux/uaccess.h> 83 + 84 + #include <linux/i2c.h> 85 + #include <linux/version.h> 86 + #include <linux/workqueue.h> 87 + #include <linux/poll.h> 88 + #include <linux/mm.h> 89 + #include <linux/fs.h> 90 + #include <linux/delay.h> 91 + #include <linux/types.h> 92 + 93 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 94 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 95 + #if (!defined(__OLD_VIDIOC_)) 96 + #define __OLD_VIDIOC_ 97 + #endif /* !defined(__OLD_VIDIOC_) */ 98 + 99 + #include <media/v4l2-dev.h> 100 + 101 + #if defined(EASYCAP_NEEDS_V4L2_DEVICE_H) 102 + #include <media/v4l2-device.h> 103 + #endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/ 104 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 105 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 106 + 107 + #if (!defined(__OLD_VIDIOC_)) 108 + #define __OLD_VIDIOC_ 109 + #endif /* !defined(__OLD_VIDIOC_) */ 110 + #include <linux/videodev2.h> 111 + 112 + #include <linux/soundcard.h> 113 + 114 + #if defined(EASYCAP_NEEDS_USBVIDEO_H) 115 + #include <config/video/usbvideo.h> 116 + #endif /*EASYCAP_NEEDS_USBVIDEO_H*/ 117 + 118 + #if (!defined(PAGE_SIZE)) 119 + #error "PAGE_SIZE not defined" 120 + #endif 121 + 122 + #define STRINGIZE_AGAIN(x) #x 123 + #define STRINGIZE(x) STRINGIZE_AGAIN(x) 124 + 125 + /*---------------------------------------------------------------------------*/ 126 + /* VENDOR, PRODUCT: Syntek Semiconductor Co., Ltd 127 + * 128 + * EITHER EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60 129 + * with input cabling: AUDIO(L), AUDIO(R), CVBS, S-VIDEO. 130 + * 131 + * OR EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002 132 + * with input cabling: MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4. 133 + */ 134 + /*---------------------------------------------------------------------------*/ 135 + #define USB_EASYCAP_VENDOR_ID 0x05e1 136 + #define USB_EASYCAP_PRODUCT_ID 0x0408 137 + 138 + #define EASYCAP_DRIVER_VERSION "0.8" 139 + #define EASYCAP_DRIVER_DESCRIPTION "easycapdc60" 140 + 141 + #define USB_SKEL_MINOR_BASE 192 142 + #define VIDEO_DEVICE_MANY 8 143 + 144 + /*---------------------------------------------------------------------------*/ 145 + /* 146 + * DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE 147 + */ 148 + /*---------------------------------------------------------------------------*/ 149 + #define SAA_0A_DEFAULT 0x7F 150 + #define SAA_0B_DEFAULT 0x3F 151 + #define SAA_0C_DEFAULT 0x2F 152 + #define SAA_0D_DEFAULT 0x00 153 + /*---------------------------------------------------------------------------*/ 154 + /* 155 + * VIDEO STREAMING PARAMETERS: 156 + * USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT 157 + * OF 3072 BYTES PER MICROFRAME for wMaxPacketSize. 158 + */ 159 + /*---------------------------------------------------------------------------*/ 160 + #define VIDEO_ISOC_BUFFER_MANY 16 161 + #define VIDEO_ISOC_ORDER 3 162 + #define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER) 163 + #define USB_2_0_MAXPACKETSIZE 3072 164 + #if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE) 165 + #error video_isoc_buffer[.] will not be big enough 166 + #endif 167 + /*---------------------------------------------------------------------------*/ 168 + /* 169 + * VIDEO BUFFERS 170 + */ 171 + /*---------------------------------------------------------------------------*/ 172 + #define FIELD_BUFFER_SIZE (203 * PAGE_SIZE) 173 + #define FRAME_BUFFER_SIZE (405 * PAGE_SIZE) 174 + #define FIELD_BUFFER_MANY 4 175 + #define FRAME_BUFFER_MANY 6 176 + /*---------------------------------------------------------------------------*/ 177 + /* 178 + * AUDIO STREAMING PARAMETERS 179 + */ 180 + /*---------------------------------------------------------------------------*/ 181 + #define AUDIO_ISOC_BUFFER_MANY 16 182 + #define AUDIO_ISOC_ORDER 3 183 + #define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER) 184 + /*---------------------------------------------------------------------------*/ 185 + /* 186 + * AUDIO BUFFERS 187 + */ 188 + /*---------------------------------------------------------------------------*/ 189 + #define AUDIO_FRAGMENT_MANY 32 190 + /*---------------------------------------------------------------------------*/ 191 + /* 192 + * STRUCTURE DEFINITIONS 193 + */ 194 + /*---------------------------------------------------------------------------*/ 195 + struct data_buffer { 196 + struct list_head list_head; 197 + void *pgo; 198 + void *pto; 199 + __u16 kount; 200 + }; 201 + /*---------------------------------------------------------------------------*/ 202 + struct data_urb { 203 + struct list_head list_head; 204 + struct urb *purb; 205 + int isbuf; 206 + int length; 207 + }; 208 + /*---------------------------------------------------------------------------*/ 209 + /* 210 + * easycap.ilk == 0 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256 211 + * easycap.ilk == 2 => CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9 212 + * easycap.ilk == 3 => FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9 213 + */ 214 + /*---------------------------------------------------------------------------*/ 215 + struct easycap { 216 + 217 + int ilk; 218 + bool microphone; 219 + 220 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 221 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 222 + struct video_device *pvideo_device; 223 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 224 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 225 + 226 + struct usb_device *pusb_device; 227 + struct usb_interface *pusb_interface; 228 + 229 + struct kref kref; 230 + 231 + struct mutex mutex_mmap_video[FRAME_BUFFER_MANY]; 232 + struct mutex mutex_timeval0; 233 + struct mutex mutex_timeval1; 234 + 235 + int queued[FRAME_BUFFER_MANY]; 236 + int done[FRAME_BUFFER_MANY]; 237 + 238 + wait_queue_head_t wq_video; 239 + wait_queue_head_t wq_audio; 240 + 241 + int input; 242 + int polled; 243 + int standard_offset; 244 + int format_offset; 245 + 246 + int fps; 247 + int usec; 248 + int tolerate; 249 + int merit[180]; 250 + 251 + struct timeval timeval0; 252 + struct timeval timeval1; 253 + struct timeval timeval2; 254 + struct timeval timeval7; 255 + long long int dnbydt; 256 + 257 + int video_interface; 258 + int video_altsetting_on; 259 + int video_altsetting_off; 260 + int video_endpointnumber; 261 + int video_isoc_maxframesize; 262 + int video_isoc_buffer_size; 263 + int video_isoc_framesperdesc; 264 + 265 + int video_isoc_streaming; 266 + int video_isoc_sequence; 267 + int video_idle; 268 + int video_eof; 269 + int video_junk; 270 + 271 + int fudge; 272 + 273 + struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY]; 274 + struct data_buffer \ 275 + field_buffer[FIELD_BUFFER_MANY][(FIELD_BUFFER_SIZE/PAGE_SIZE)]; 276 + struct data_buffer \ 277 + frame_buffer[FRAME_BUFFER_MANY][(FRAME_BUFFER_SIZE/PAGE_SIZE)]; 278 + 279 + struct list_head urb_video_head; 280 + struct list_head *purb_video_head; 281 + 282 + int vma_many; 283 + 284 + /*---------------------------------------------------------------------------*/ 285 + /* 286 + * BUFFER INDICATORS 287 + */ 288 + /*---------------------------------------------------------------------------*/ 289 + int field_fill; /* Field buffer being filled by easycap_complete(). */ 290 + /* Bumped only by easycap_complete(). */ 291 + int field_page; /* Page of field buffer page being filled by */ 292 + /* easycap_complete(). */ 293 + int field_read; /* Field buffer to be read by field2frame(). */ 294 + /* Bumped only by easycap_complete(). */ 295 + int frame_fill; /* Frame buffer being filled by field2frame(). */ 296 + /* Bumped only by easycap_dqbuf() when */ 297 + /* field2frame() has created a complete frame. */ 298 + int frame_read; /* Frame buffer offered to user by DQBUF. */ 299 + /* Set only by easycap_dqbuf() to trail frame_fill.*/ 300 + int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF */ 301 + /*---------------------------------------------------------------------------*/ 302 + /* 303 + * IMAGE PROPERTIES 304 + */ 305 + /*---------------------------------------------------------------------------*/ 306 + __u32 pixelformat; 307 + __u32 field; 308 + int width; 309 + int height; 310 + int bytesperpixel; 311 + bool byteswaporder; 312 + bool decimatepixel; 313 + bool offerfields; 314 + int frame_buffer_used; 315 + int frame_buffer_many; 316 + int videofieldamount; 317 + 318 + int brightness; 319 + int contrast; 320 + int saturation; 321 + int hue; 322 + 323 + int allocation_video_urb; 324 + int allocation_video_page; 325 + int allocation_video_struct; 326 + int registered_video; 327 + /*---------------------------------------------------------------------------*/ 328 + /* 329 + * SOUND PROPERTIES 330 + */ 331 + /*---------------------------------------------------------------------------*/ 332 + int audio_interface; 333 + int audio_altsetting_on; 334 + int audio_altsetting_off; 335 + int audio_endpointnumber; 336 + int audio_isoc_maxframesize; 337 + int audio_isoc_buffer_size; 338 + int audio_isoc_framesperdesc; 339 + 340 + int audio_isoc_streaming; 341 + int audio_idle; 342 + int audio_eof; 343 + int volume; 344 + int mute; 345 + 346 + struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY]; 347 + 348 + struct list_head urb_audio_head; 349 + struct list_head *purb_audio_head; 350 + /*---------------------------------------------------------------------------*/ 351 + /* 352 + * BUFFER INDICATORS 353 + */ 354 + /*---------------------------------------------------------------------------*/ 355 + int audio_fill; /* Audio buffer being filled by easysnd_complete(). */ 356 + /* Bumped only by easysnd_complete(). */ 357 + int audio_read; /* Audio buffer page being read by easysnd_read(). */ 358 + /* Set by easysnd_read() to trail audio_fill by */ 359 + /* one fragment. */ 360 + /*---------------------------------------------------------------------------*/ 361 + /* 362 + * SOUND PROPERTIES 363 + */ 364 + /*---------------------------------------------------------------------------*/ 365 + 366 + int audio_buffer_many; 367 + 368 + int allocation_audio_urb; 369 + int allocation_audio_page; 370 + int allocation_audio_struct; 371 + int registered_audio; 372 + 373 + long long int audio_sample; 374 + long long int audio_niveau; 375 + long long int audio_square; 376 + 377 + struct data_buffer audio_buffer[]; 378 + }; 379 + /*---------------------------------------------------------------------------*/ 380 + struct easycap_standard { 381 + __u16 mask; 382 + struct v4l2_standard v4l2_standard; 383 + }; 384 + struct easycap_format { 385 + __u16 mask; 386 + char name[128]; 387 + struct v4l2_format v4l2_format; 388 + }; 389 + /*---------------------------------------------------------------------------*/ 390 + /* 391 + * VIDEO FUNCTION PROTOTYPES 392 + */ 393 + /*---------------------------------------------------------------------------*/ 394 + void easycap_complete(struct urb *); 395 + int easycap_open(struct inode *, struct file *); 396 + int easycap_release(struct inode *, struct file *); 397 + int easycap_ioctl(struct inode *, struct file *, \ 398 + unsigned int, unsigned long); 399 + 400 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 401 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 402 + int easycap_open_noinode(struct file *); 403 + int easycap_release_noinode(struct file *); 404 + long easycap_ioctl_noinode(struct file *, \ 405 + unsigned int, unsigned long); 406 + int videodev_release(struct video_device *); 407 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 408 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 409 + 410 + unsigned int easycap_poll(struct file *, poll_table *); 411 + int easycap_mmap(struct file *, struct vm_area_struct *); 412 + int easycap_usb_probe(struct usb_interface *, \ 413 + const struct usb_device_id *); 414 + void easycap_usb_disconnect(struct usb_interface *); 415 + void easycap_delete(struct kref *); 416 + 417 + void easycap_vma_open(struct vm_area_struct *); 418 + void easycap_vma_close(struct vm_area_struct *); 419 + int easycap_vma_fault(struct vm_area_struct *, struct vm_fault *); 420 + int easycap_dqbuf(struct easycap *, int); 421 + int submit_video_urbs(struct easycap *); 422 + int kill_video_urbs(struct easycap *); 423 + int field2frame(struct easycap *); 424 + int redaub(struct easycap *, void *, void *, \ 425 + int, int, __u8, __u8, bool); 426 + void debrief(struct easycap *); 427 + void sayreadonly(struct easycap *); 428 + void easycap_testcard(struct easycap *, int); 429 + int explain_ioctl(__u32); 430 + int explain_cid(__u32); 431 + int fillin_formats(void); 432 + int adjust_standard(struct easycap *, v4l2_std_id); 433 + int adjust_format(struct easycap *, __u32, __u32, __u32, \ 434 + int, bool); 435 + int adjust_brightness(struct easycap *, int); 436 + int adjust_contrast(struct easycap *, int); 437 + int adjust_saturation(struct easycap *, int); 438 + int adjust_hue(struct easycap *, int); 439 + int adjust_volume(struct easycap *, int); 440 + /*---------------------------------------------------------------------------*/ 441 + /* 442 + * AUDIO FUNCTION PROTOTYPES 443 + */ 444 + /*---------------------------------------------------------------------------*/ 445 + void easysnd_complete(struct urb *); 446 + ssize_t easysnd_read(struct file *, char __user *, size_t, loff_t *); 447 + int easysnd_open(struct inode *, struct file *); 448 + int easysnd_release(struct inode *, struct file *); 449 + int easysnd_ioctl(struct inode *, struct file *, \ 450 + unsigned int, unsigned long); 451 + unsigned int easysnd_poll(struct file *, poll_table *); 452 + void easysnd_delete(struct kref *); 453 + int submit_audio_urbs(struct easycap *); 454 + int kill_audio_urbs(struct easycap *); 455 + void easysnd_testtone(struct easycap *, int); 456 + int audio_setup(struct easycap *); 457 + /*---------------------------------------------------------------------------*/ 458 + /* 459 + * LOW-LEVEL FUNCTION PROTOTYPES 460 + */ 461 + /*---------------------------------------------------------------------------*/ 462 + int audio_gainget(struct usb_device *); 463 + int audio_gainset(struct usb_device *, __s8); 464 + 465 + int set_interface(struct usb_device *, __u16); 466 + int wakeup_device(struct usb_device *); 467 + int confirm_resolution(struct usb_device *); 468 + int confirm_stream(struct usb_device *); 469 + 470 + int setup_stk(struct usb_device *); 471 + int setup_saa(struct usb_device *); 472 + int setup_vt(struct usb_device *); 473 + int check_stk(struct usb_device *); 474 + int check_saa(struct usb_device *); 475 + int ready_saa(struct usb_device *); 476 + int merit_saa(struct usb_device *); 477 + int check_vt(struct usb_device *); 478 + int select_input(struct usb_device *, int, int); 479 + int set_resolution(struct usb_device *, \ 480 + __u16, __u16, __u16, __u16); 481 + 482 + int read_saa(struct usb_device *, __u16); 483 + int read_stk(struct usb_device *, __u32); 484 + int write_saa(struct usb_device *, __u16, __u16); 485 + int wait_i2c(struct usb_device *); 486 + int write_000(struct usb_device *, __u16, __u16); 487 + int start_100(struct usb_device *); 488 + int stop_100(struct usb_device *); 489 + int write_300(struct usb_device *); 490 + int read_vt(struct usb_device *, __u16); 491 + int write_vt(struct usb_device *, __u16, __u16); 492 + 493 + int set2to78(struct usb_device *); 494 + int set2to93(struct usb_device *); 495 + 496 + int regset(struct usb_device *, __u16, __u16); 497 + int regget(struct usb_device *, __u16, void *); 498 + /*---------------------------------------------------------------------------*/ 499 + struct signed_div_result { 500 + long long int quotient; 501 + unsigned long long int remainder; 502 + } signed_div(long long int, long long int); 503 + /*---------------------------------------------------------------------------*/ 504 + /* 505 + * IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND, 506 + * ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND. 507 + * THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE. NOT 508 + * ONLY MUST THE PARAMETER 509 + * STANDARD_MANY 510 + * BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE 511 + * NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE: DUMMY STANDARDS 512 + * MAY NEED TO BE ADDED. APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN 513 + * ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE. BEWARE. 514 + */ 515 + /*---------------------------------------------------------------------------*/ 516 + #define PAL_BGHIN 0 517 + #define PAL_Nc 2 518 + #define SECAM 4 519 + #define NTSC_N 6 520 + #define NTSC_N_443 8 521 + #define NTSC_M 1 522 + #define NTSC_443 3 523 + #define NTSC_M_JP 5 524 + #define PAL_60 7 525 + #define PAL_M 9 526 + #define STANDARD_MANY 10 527 + /*---------------------------------------------------------------------------*/ 528 + /* 529 + * ENUMS 530 + */ 531 + /*---------------------------------------------------------------------------*/ 532 + enum { 533 + AT_720x576, 534 + AT_704x576, 535 + AT_640x480, 536 + AT_720x480, 537 + AT_360x288, 538 + AT_320x240, 539 + AT_360x240, 540 + RESOLUTION_MANY 541 + }; 542 + enum { 543 + FMT_UYVY, 544 + FMT_YUY2, 545 + FMT_RGB24, 546 + FMT_RGB32, 547 + FMT_BGR24, 548 + FMT_BGR32, 549 + PIXELFORMAT_MANY 550 + }; 551 + enum { 552 + FIELD_NONE, 553 + FIELD_INTERLACED, 554 + FIELD_ALTERNATE, 555 + INTERLACE_MANY 556 + }; 557 + #define SETTINGS_MANY (STANDARD_MANY * \ 558 + RESOLUTION_MANY * \ 559 + 2 * \ 560 + PIXELFORMAT_MANY * \ 561 + INTERLACE_MANY) 562 + /*---------------------------------------------------------------------------*/ 563 + /* 564 + * MACROS 565 + */ 566 + /*---------------------------------------------------------------------------*/ 567 + #define GET(X, Y, Z) do { \ 568 + int rc; \ 569 + *(Z) = (__u16)0; \ 570 + rc = regget(X, Y, Z); \ 571 + if (0 > rc) { \ 572 + JOT(8, ":-(%i\n", __LINE__); return(rc); \ 573 + } \ 574 + } while (0) 575 + 576 + #define SET(X, Y, Z) do { \ 577 + int rc; \ 578 + rc = regset(X, Y, Z); \ 579 + if (0 > rc) { \ 580 + JOT(8, ":-(%i\n", __LINE__); return(rc); \ 581 + } \ 582 + } while (0) 583 + /*---------------------------------------------------------------------------*/ 584 + 585 + #define SAY(format, args...) do { \ 586 + printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \ 587 + } while (0) 588 + 589 + 590 + #if defined(EASYCAP_DEBUG) 591 + #define JOT(n, format, args...) do { \ 592 + if (n <= easycap_debug) { \ 593 + printk(KERN_DEBUG "easycap: %s: " format, __func__, ##args); \ 594 + } \ 595 + } while (0) 596 + #else 597 + #define JOT(n, format, args...) do {} while (0) 598 + #endif /*EASYCAP_DEBUG*/ 599 + 600 + #define POUT JOT(8, ":-(in file %s line %4i\n", __FILE__, __LINE__) 601 + 602 + #define MICROSECONDS(X, Y) \ 603 + ((1000000*((long long int)(X.tv_sec - Y.tv_sec))) + \ 604 + (long long int)(X.tv_usec - Y.tv_usec)) 605 + 606 + /*---------------------------------------------------------------------------*/ 607 + /* 608 + * (unsigned char *)P pointer to next byte pair 609 + * (long int *)X pointer to accumulating count 610 + * (long int *)Y pointer to accumulating sum 611 + * (long long int *)Z pointer to accumulating sum of squares 612 + */ 613 + /*---------------------------------------------------------------------------*/ 614 + #define SUMMER(P, X, Y, Z) do { \ 615 + unsigned char *p; \ 616 + unsigned int u0, u1, u2; \ 617 + long int s; \ 618 + p = (unsigned char *)(P); \ 619 + u0 = (unsigned int) (*p); \ 620 + u1 = (unsigned int) (*(p + 1)); \ 621 + u2 = (unsigned int) ((u1 << 8) | u0); \ 622 + if (0x8000 & u2) \ 623 + s = -(long int)(0x7FFF & (~u2)); \ 624 + else \ 625 + s = (long int)(0x7FFF & u2); \ 626 + *((X)) += (long int) 1; \ 627 + *((Y)) += (long int) s; \ 628 + *((Z)) += ((long long int)(s) * (long long int)(s)); \ 629 + } while (0) 630 + /*---------------------------------------------------------------------------*/ 631 + 632 + #endif /*EASYCAP_H*/
+27
drivers/staging/easycap/easycap_debug.h
··· 1 + /***************************************************************************** 2 + * * 3 + * easycap_debug.h * 4 + * * 5 + *****************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + extern int easycap_debug;
+2651
drivers/staging/easycap/easycap_ioctl.c
··· 1 + /****************************************************************************** 2 + * * 3 + * easycap_ioctl.c * 4 + * * 5 + ******************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + 28 + #include "easycap.h" 29 + #include "easycap_debug.h" 30 + #include "easycap_standard.h" 31 + #include "easycap_ioctl.h" 32 + 33 + /*--------------------------------------------------------------------------*/ 34 + /* 35 + * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE 36 + * FOLLOWING: 37 + * peasycap->standard_offset 38 + * peasycap->fps 39 + * peasycap->usec 40 + * peasycap->tolerate 41 + */ 42 + /*---------------------------------------------------------------------------*/ 43 + int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id) 44 + { 45 + struct easycap_standard *peasycap_standard; 46 + __u16 reg, set; 47 + int ir, rc, need; 48 + unsigned int itwas, isnow; 49 + 50 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 51 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 52 + return -EFAULT; 53 + } 54 + peasycap_standard = &easycap_standard[0]; 55 + while (0xFFFF != peasycap_standard->mask) { 56 + if (std_id & peasycap_standard->v4l2_standard.id) 57 + break; 58 + peasycap_standard++; 59 + } 60 + if (0xFFFF == peasycap_standard->mask) { 61 + SAY("ERROR: 0x%08X=std_id: standard not found\n", \ 62 + (unsigned int)std_id); 63 + return -EINVAL; 64 + } 65 + SAY("user requests standard: %s\n", \ 66 + &(peasycap_standard->v4l2_standard.name[0])); 67 + if (peasycap->standard_offset == \ 68 + (int)(peasycap_standard - &easycap_standard[0])) { 69 + SAY("requested standard already in effect\n"); 70 + return 0; 71 + } 72 + peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]); 73 + peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \ 74 + peasycap_standard->v4l2_standard.frameperiod.numerator; 75 + if (!peasycap->fps) { 76 + SAY("MISTAKE: frames-per-second is zero\n"); 77 + return -EFAULT; 78 + } 79 + JOT(8, "%i frames-per-second\n", peasycap->fps); 80 + peasycap->usec = 1000000 / (2 * peasycap->fps); 81 + peasycap->tolerate = 1000 * (25 / peasycap->fps); 82 + 83 + kill_video_urbs(peasycap); 84 + 85 + /*--------------------------------------------------------------------------*/ 86 + /* 87 + * SAA7113H DATASHEET PAGE 44, TABLE 42 88 + */ 89 + /*--------------------------------------------------------------------------*/ 90 + need = 0; itwas = 0; reg = 0x00; set = 0x00; 91 + switch (peasycap_standard->mask & 0x000F) { 92 + case NTSC_M_JP: { 93 + reg = 0x0A; set = 0x95; 94 + ir = read_saa(peasycap->pusb_device, reg); 95 + if (0 > ir) 96 + SAY("ERROR: cannot read SAA register 0x%02X\n", reg); 97 + else 98 + itwas = (unsigned int)ir; 99 + 100 + 101 + set2to78(peasycap->pusb_device); 102 + 103 + 104 + rc = write_saa(peasycap->pusb_device, reg, set); 105 + if (0 != rc) 106 + SAY("ERROR: failed to set SAA register " \ 107 + "0x%02X to 0x%02X for JP standard\n", reg, set); 108 + else { 109 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 110 + if (0 > ir) 111 + JOT(8, "SAA register 0x%02X changed " \ 112 + "to 0x%02X\n", reg, isnow); 113 + else 114 + JOT(8, "SAA register 0x%02X changed " \ 115 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 116 + 117 + set2to78(peasycap->pusb_device); 118 + 119 + } 120 + 121 + reg = 0x0B; set = 0x48; 122 + ir = read_saa(peasycap->pusb_device, reg); 123 + if (0 > ir) 124 + SAY("ERROR: cannot read SAA register 0x%02X\n", reg); 125 + else 126 + itwas = (unsigned int)ir; 127 + 128 + set2to78(peasycap->pusb_device); 129 + 130 + rc = write_saa(peasycap->pusb_device, reg, set); 131 + if (0 != rc) 132 + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X " \ 133 + "for JP standard\n", reg, set); 134 + else { 135 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 136 + if (0 > ir) 137 + JOT(8, "SAA register 0x%02X changed " \ 138 + "to 0x%02X\n", reg, isnow); 139 + else 140 + JOT(8, "SAA register 0x%02X changed " \ 141 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 142 + 143 + set2to78(peasycap->pusb_device); 144 + 145 + } 146 + /*--------------------------------------------------------------------------*/ 147 + /* 148 + * NOTE: NO break HERE: RUN ON TO NEXT CASE 149 + */ 150 + /*--------------------------------------------------------------------------*/ 151 + } 152 + case NTSC_M: 153 + case PAL_BGHIN: { 154 + reg = 0x0E; set = 0x01; need = 1; break; 155 + } 156 + case NTSC_N_443: 157 + case PAL_60: { 158 + reg = 0x0E; set = 0x11; need = 1; break; 159 + } 160 + case NTSC_443: 161 + case PAL_Nc: { 162 + reg = 0x0E; set = 0x21; need = 1; break; 163 + } 164 + case NTSC_N: 165 + case PAL_M: { 166 + reg = 0x0E; set = 0x31; need = 1; break; 167 + } 168 + case SECAM: { 169 + reg = 0x0E; set = 0x51; need = 1; break; 170 + } 171 + default: 172 + break; 173 + } 174 + /*--------------------------------------------------------------------------*/ 175 + if (need) { 176 + ir = read_saa(peasycap->pusb_device, reg); 177 + if (0 > ir) 178 + SAY("ERROR: failed to read SAA register 0x%02X\n", reg); 179 + else 180 + itwas = (unsigned int)ir; 181 + 182 + set2to78(peasycap->pusb_device); 183 + 184 + rc = write_saa(peasycap->pusb_device, reg, set); 185 + if (0 != write_saa(peasycap->pusb_device, reg, set)) { 186 + SAY("ERROR: failed to set SAA register " \ 187 + "0x%02X to 0x%02X for table 42\n", reg, set); 188 + } else { 189 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 190 + if (0 > ir) 191 + JOT(8, "SAA register 0x%02X changed " \ 192 + "to 0x%02X\n", reg, isnow); 193 + else 194 + JOT(8, "SAA register 0x%02X changed " \ 195 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 196 + } 197 + } 198 + /*--------------------------------------------------------------------------*/ 199 + /* 200 + * SAA7113H DATASHEET PAGE 41 201 + */ 202 + /*--------------------------------------------------------------------------*/ 203 + reg = 0x08; 204 + ir = read_saa(peasycap->pusb_device, reg); 205 + if (0 > ir) 206 + SAY("ERROR: failed to read SAA register 0x%02X " \ 207 + "so cannot reset\n", reg); 208 + else { 209 + itwas = (unsigned int)ir; 210 + if (peasycap_standard->mask & 0x0001) 211 + set = itwas | 0x40 ; 212 + else 213 + set = itwas & ~0x40 ; 214 + 215 + set2to78(peasycap->pusb_device); 216 + 217 + rc = write_saa(peasycap->pusb_device, reg, set); 218 + if (0 != rc) 219 + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set); 220 + else { 221 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 222 + if (0 > ir) 223 + JOT(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow); 224 + else 225 + JOT(8, "SAA register 0x%02X changed " \ 226 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 227 + } 228 + } 229 + /*--------------------------------------------------------------------------*/ 230 + /* 231 + * SAA7113H DATASHEET PAGE 51, TABLE 57 232 + */ 233 + /*---------------------------------------------------------------------------*/ 234 + reg = 0x40; 235 + ir = read_saa(peasycap->pusb_device, reg); 236 + if (0 > ir) 237 + SAY("ERROR: failed to read SAA register 0x%02X " \ 238 + "so cannot reset\n", reg); 239 + else { 240 + itwas = (unsigned int)ir; 241 + if (peasycap_standard->mask & 0x0001) 242 + set = itwas | 0x80 ; 243 + else 244 + set = itwas & ~0x80 ; 245 + 246 + set2to78(peasycap->pusb_device); 247 + 248 + rc = write_saa(peasycap->pusb_device, reg, set); 249 + if (0 != rc) 250 + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", reg, set); 251 + else { 252 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 253 + if (0 > ir) 254 + JOT(8, "SAA register 0x%02X changed to 0x%02X\n", reg, isnow); 255 + else 256 + JOT(8, "SAA register 0x%02X changed " \ 257 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 258 + } 259 + } 260 + /*--------------------------------------------------------------------------*/ 261 + /* 262 + * SAA7113H DATASHEET PAGE 53, TABLE 66 263 + */ 264 + /*--------------------------------------------------------------------------*/ 265 + reg = 0x5A; 266 + ir = read_saa(peasycap->pusb_device, reg); 267 + if (0 > ir) 268 + SAY("ERROR: failed to read SAA register 0x%02X but continuing\n", reg); 269 + itwas = (unsigned int)ir; 270 + if (peasycap_standard->mask & 0x0001) 271 + set = 0x0A ; 272 + else 273 + set = 0x07 ; 274 + 275 + set2to78(peasycap->pusb_device); 276 + 277 + if (0 != write_saa(peasycap->pusb_device, reg, set)) 278 + SAY("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \ 279 + reg, set); 280 + else { 281 + isnow = (unsigned int)read_saa(peasycap->pusb_device, reg); 282 + if (0 > ir) 283 + JOT(8, "SAA register 0x%02X changed " 284 + "to 0x%02X\n", reg, isnow); 285 + else 286 + JOT(8, "SAA register 0x%02X changed " 287 + "from 0x%02X to 0x%02X\n", reg, itwas, isnow); 288 + } 289 + if (0 != check_saa(peasycap->pusb_device)) 290 + SAY("ERROR: check_saa() failed\n"); 291 + return 0; 292 + } 293 + /*****************************************************************************/ 294 + /*--------------------------------------------------------------------------*/ 295 + /* 296 + * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL DEPENDS ON THE 297 + * CURRENT VALUE OF peasycap->standard_offset. 298 + * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN 299 + * THIS ROUTINE UPDATES THE FOLLOWING: 300 + * peasycap->format_offset 301 + * peasycap->pixelformat 302 + * peasycap->field 303 + * peasycap->height 304 + * peasycap->width 305 + * peasycap->bytesperpixel 306 + * peasycap->byteswaporder 307 + * peasycap->decimatepixel 308 + * peasycap->frame_buffer_used 309 + * peasycap->videofieldamount 310 + * peasycap->offerfields 311 + * 312 + * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[] 313 + * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER. 314 + * ERRORS RETURN A NEGATIVE NUMBER. 315 + */ 316 + /*--------------------------------------------------------------------------*/ 317 + int adjust_format(struct easycap *peasycap, \ 318 + __u32 width, __u32 height, __u32 pixelformat, int field, bool try) 319 + { 320 + struct easycap_format *peasycap_format, *peasycap_best_format; 321 + __u16 mask; 322 + struct usb_device *p; 323 + int miss, multiplier, best; 324 + char bf[5], *pc; 325 + __u32 uc; 326 + 327 + if ((struct easycap *)NULL == peasycap) { 328 + SAY("ERROR: peasycap is NULL\n"); 329 + return -EFAULT; 330 + } 331 + p = peasycap->pusb_device; 332 + if ((struct usb_device *)NULL == p) { 333 + SAY("ERROR: peaycap->pusb_device is NULL\n"); 334 + return -EFAULT; 335 + } 336 + pc = &bf[0]; 337 + uc = pixelformat; memcpy((void *)pc, (void *)(&uc), 4); bf[4] = 0; 338 + mask = easycap_standard[peasycap->standard_offset].mask; 339 + SAY("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \ 340 + width, height, pc, pixelformat, field, mask); 341 + if (V4L2_FIELD_ANY == field) { 342 + field = V4L2_FIELD_INTERLACED; 343 + SAY("prefer: V4L2_FIELD_INTERLACED=field, was V4L2_FIELD_ANY\n"); 344 + } 345 + peasycap_best_format = (struct easycap_format *)NULL; 346 + peasycap_format = &easycap_format[0]; 347 + while (0 != peasycap_format->v4l2_format.fmt.pix.width) { 348 + JOT(16, ".> %i %i 0x%08X %ix%i\n", \ 349 + peasycap_format->mask & 0x01, 350 + peasycap_format->v4l2_format.fmt.pix.field, 351 + peasycap_format->v4l2_format.fmt.pix.pixelformat, 352 + peasycap_format->v4l2_format.fmt.pix.width, 353 + peasycap_format->v4l2_format.fmt.pix.height); 354 + 355 + if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \ 356 + (peasycap_format->v4l2_format.fmt.pix.field == field) && \ 357 + (peasycap_format->v4l2_format.fmt.pix.pixelformat == \ 358 + pixelformat) && \ 359 + (peasycap_format->v4l2_format.fmt.pix.width == width) && \ 360 + (peasycap_format->v4l2_format.fmt.pix.height == height)) { 361 + peasycap_best_format = peasycap_format; 362 + break; 363 + } 364 + peasycap_format++; 365 + } 366 + if (0 == peasycap_format->v4l2_format.fmt.pix.width) { 367 + SAY("cannot do: %ix%i with standard mask 0x%02X\n", \ 368 + width, height, mask); 369 + peasycap_format = &easycap_format[0]; best = -1; 370 + while (0 != peasycap_format->v4l2_format.fmt.pix.width) { 371 + if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \ 372 + (peasycap_format->v4l2_format.fmt.pix\ 373 + .field == field) && \ 374 + (peasycap_format->v4l2_format.fmt.pix\ 375 + .pixelformat == pixelformat)) { 376 + miss = abs(peasycap_format->\ 377 + v4l2_format.fmt.pix.width - width); 378 + if ((best > miss) || (best < 0)) { 379 + best = miss; 380 + peasycap_best_format = peasycap_format; 381 + if (!miss) 382 + break; 383 + } 384 + } 385 + peasycap_format++; 386 + } 387 + if (-1 == best) { 388 + SAY("cannot do %ix... with standard mask 0x%02X\n", \ 389 + width, mask); 390 + SAY("cannot do ...x%i with standard mask 0x%02X\n", \ 391 + height, mask); 392 + SAY(" %ix%i unmatched\n", width, height); 393 + return peasycap->format_offset; 394 + } 395 + } 396 + if ((struct easycap_format *)NULL == peasycap_best_format) { 397 + SAY("MISTAKE: peasycap_best_format is NULL"); 398 + return -EINVAL; 399 + } 400 + peasycap_format = peasycap_best_format; 401 + 402 + /*...........................................................................*/ 403 + if (true == try) 404 + return (int)(peasycap_best_format - &easycap_format[0]); 405 + /*...........................................................................*/ 406 + 407 + if (false != try) { 408 + SAY("MISTAKE: true==try where is should be false\n"); 409 + return -EINVAL; 410 + } 411 + SAY("actioning: %ix%i %s\n", \ 412 + peasycap_format->v4l2_format.fmt.pix.width, \ 413 + peasycap_format->v4l2_format.fmt.pix.height, 414 + &peasycap_format->name[0]); 415 + peasycap->height = peasycap_format->v4l2_format.fmt.pix.height; 416 + peasycap->width = peasycap_format->v4l2_format.fmt.pix.width; 417 + peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat; 418 + peasycap->field = peasycap_format->v4l2_format.fmt.pix.field; 419 + peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]); 420 + peasycap->bytesperpixel = (0x00F0 & peasycap_format->mask) >> 4 ; 421 + if (0x0100 & peasycap_format->mask) 422 + peasycap->byteswaporder = true; 423 + else 424 + peasycap->byteswaporder = false; 425 + if (0x0800 & peasycap_format->mask) 426 + peasycap->decimatepixel = true; 427 + else 428 + peasycap->decimatepixel = false; 429 + if (0x1000 & peasycap_format->mask) 430 + peasycap->offerfields = true; 431 + else 432 + peasycap->offerfields = false; 433 + if (true == peasycap->decimatepixel) 434 + multiplier = 2; 435 + else 436 + multiplier = 1; 437 + peasycap->videofieldamount = multiplier * peasycap->width * \ 438 + multiplier * peasycap->height; 439 + peasycap->frame_buffer_used = peasycap->bytesperpixel * \ 440 + peasycap->width * peasycap->height; 441 + 442 + if (true == peasycap->offerfields) { 443 + SAY("WARNING: %i=peasycap->field is untested: " \ 444 + "please report problems\n", peasycap->field); 445 + 446 + 447 + /* 448 + * FIXME ---- THIS IS UNTESTED, MAY BE (AND PROBABLY IS) INCORRECT: 449 + * 450 + * peasycap->frame_buffer_used = peasycap->frame_buffer_used / 2; 451 + * 452 + * SO DO NOT RISK IT YET. 453 + * 454 + */ 455 + 456 + 457 + 458 + } 459 + 460 + kill_video_urbs(peasycap); 461 + 462 + /*---------------------------------------------------------------------------*/ 463 + /* 464 + * PAL 465 + */ 466 + /*---------------------------------------------------------------------------*/ 467 + if (0 == (0x01 & peasycap_format->mask)) { 468 + if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \ 469 + (576 == \ 470 + peasycap_format->v4l2_format.fmt.pix.height)) || \ 471 + ((360 == \ 472 + peasycap_format->v4l2_format.fmt.pix.width) && \ 473 + (288 == \ 474 + peasycap_format->v4l2_format.fmt.pix.height))) { 475 + if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) { 476 + SAY("ERROR: set_resolution() failed\n"); 477 + return -EINVAL; 478 + } 479 + } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \ 480 + (576 == peasycap_format->v4l2_format.fmt.pix.height)) { 481 + if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) { 482 + SAY("ERROR: set_resolution() failed\n"); 483 + return -EINVAL; 484 + } 485 + } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \ 486 + (480 == \ 487 + peasycap_format->v4l2_format.fmt.pix.height)) || \ 488 + ((320 == \ 489 + peasycap_format->v4l2_format.fmt.pix.width) && \ 490 + (240 == \ 491 + peasycap_format->v4l2_format.fmt.pix.height))) { 492 + if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) { 493 + SAY("ERROR: set_resolution() failed\n"); 494 + return -EINVAL; 495 + } 496 + } else { 497 + SAY("MISTAKE: bad format, cannot set resolution\n"); 498 + return -EINVAL; 499 + } 500 + /*---------------------------------------------------------------------------*/ 501 + /* 502 + * NTSC 503 + */ 504 + /*---------------------------------------------------------------------------*/ 505 + } else { 506 + if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \ 507 + (480 == \ 508 + peasycap_format->v4l2_format.fmt.pix.height)) || \ 509 + ((360 == \ 510 + peasycap_format->v4l2_format.fmt.pix.width) && \ 511 + (240 == \ 512 + peasycap_format->v4l2_format.fmt.pix.height))) { 513 + if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) { 514 + SAY("ERROR: set_resolution() failed\n"); 515 + return -EINVAL; 516 + } 517 + } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \ 518 + (480 == \ 519 + peasycap_format->v4l2_format.fmt.pix.height)) || \ 520 + ((320 == \ 521 + peasycap_format->v4l2_format.fmt.pix.width) && \ 522 + (240 == \ 523 + peasycap_format->v4l2_format.fmt.pix.height))) { 524 + if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) { 525 + SAY("ERROR: set_resolution() failed\n"); 526 + return -EINVAL; 527 + } 528 + } else { 529 + SAY("MISTAKE: bad format, cannot set resolution\n"); 530 + return -EINVAL; 531 + } 532 + } 533 + /*---------------------------------------------------------------------------*/ 534 + 535 + check_stk(peasycap->pusb_device); 536 + 537 + return (int)(peasycap_best_format - &easycap_format[0]); 538 + } 539 + /*****************************************************************************/ 540 + int adjust_brightness(struct easycap *peasycap, int value) 541 + { 542 + unsigned int mood; 543 + int i1; 544 + 545 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 546 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 547 + return -EFAULT; 548 + } 549 + i1 = 0; 550 + while (0xFFFFFFFF != easycap_control[i1].id) { 551 + if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) { 552 + if ((easycap_control[i1].minimum > value) || \ 553 + (easycap_control[i1].maximum < value)) 554 + value = easycap_control[i1].default_value; 555 + peasycap->brightness = value; 556 + mood = 0x00FF & (unsigned int)peasycap->brightness; 557 + 558 + set2to78(peasycap->pusb_device); 559 + 560 + if (!write_saa(peasycap->pusb_device, 0x0A, mood)) { 561 + SAY("adjusting brightness to 0x%02X\n", mood); 562 + return 0; 563 + } else { 564 + SAY("WARNING: failed to adjust brightness " \ 565 + "to 0x%02X\n", mood); 566 + return -ENOENT; 567 + } 568 + 569 + set2to78(peasycap->pusb_device); 570 + 571 + break; 572 + } 573 + i1++; 574 + } 575 + SAY("WARNING: failed to adjust brightness: control not found\n"); 576 + return -ENOENT; 577 + } 578 + /*****************************************************************************/ 579 + int adjust_contrast(struct easycap *peasycap, int value) 580 + { 581 + unsigned int mood; 582 + int i1; 583 + 584 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 585 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 586 + return -EFAULT; 587 + } 588 + i1 = 0; 589 + while (0xFFFFFFFF != easycap_control[i1].id) { 590 + if (V4L2_CID_CONTRAST == easycap_control[i1].id) { 591 + if ((easycap_control[i1].minimum > value) || \ 592 + (easycap_control[i1].maximum < value)) 593 + value = easycap_control[i1].default_value; 594 + peasycap->contrast = value; 595 + mood = 0x00FF & (unsigned int) (peasycap->contrast - 128); 596 + 597 + set2to78(peasycap->pusb_device); 598 + 599 + if (!write_saa(peasycap->pusb_device, 0x0B, mood)) { 600 + SAY("adjusting contrast to 0x%02X\n", mood); 601 + return 0; 602 + } else { 603 + SAY("WARNING: failed to adjust contrast to " \ 604 + "0x%02X\n", mood); 605 + return -ENOENT; 606 + } 607 + 608 + set2to78(peasycap->pusb_device); 609 + 610 + break; 611 + } 612 + i1++; 613 + } 614 + SAY("WARNING: failed to adjust contrast: control not found\n"); 615 + return -ENOENT; 616 + } 617 + /*****************************************************************************/ 618 + int adjust_saturation(struct easycap *peasycap, int value) 619 + { 620 + unsigned int mood; 621 + int i1; 622 + 623 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 624 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 625 + return -EFAULT; 626 + } 627 + i1 = 0; 628 + while (0xFFFFFFFF != easycap_control[i1].id) { 629 + if (V4L2_CID_SATURATION == easycap_control[i1].id) { 630 + if ((easycap_control[i1].minimum > value) || \ 631 + (easycap_control[i1].maximum < value)) 632 + value = easycap_control[i1].default_value; 633 + peasycap->saturation = value; 634 + mood = 0x00FF & (unsigned int) (peasycap->saturation - 128); 635 + 636 + set2to78(peasycap->pusb_device); 637 + 638 + if (!write_saa(peasycap->pusb_device, 0x0C, mood)) { 639 + SAY("adjusting saturation to 0x%02X\n", mood); 640 + return 0; 641 + } else { 642 + SAY("WARNING: failed to adjust saturation to " \ 643 + "0x%02X\n", mood); 644 + return -ENOENT; 645 + } 646 + break; 647 + 648 + set2to78(peasycap->pusb_device); 649 + 650 + } 651 + i1++; 652 + } 653 + SAY("WARNING: failed to adjust saturation: control not found\n"); 654 + return -ENOENT; 655 + } 656 + /*****************************************************************************/ 657 + int adjust_hue(struct easycap *peasycap, int value) 658 + { 659 + unsigned int mood; 660 + int i1, i2; 661 + 662 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 663 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 664 + return -EFAULT; 665 + } 666 + i1 = 0; 667 + while (0xFFFFFFFF != easycap_control[i1].id) { 668 + if (V4L2_CID_HUE == easycap_control[i1].id) { 669 + if ((easycap_control[i1].minimum > value) || \ 670 + (easycap_control[i1].maximum < value)) 671 + value = easycap_control[i1].default_value; 672 + peasycap->hue = value; 673 + i2 = peasycap->hue - 128; 674 + mood = 0x00FF & ((int) i2); 675 + 676 + set2to78(peasycap->pusb_device); 677 + 678 + if (!write_saa(peasycap->pusb_device, 0x0D, mood)) { 679 + SAY("adjusting hue to 0x%02X\n", mood); 680 + return 0; 681 + } else { 682 + SAY("WARNING: failed to adjust hue to 0x%02X\n", mood); 683 + return -ENOENT; 684 + } 685 + 686 + set2to78(peasycap->pusb_device); 687 + 688 + break; 689 + } 690 + i1++; 691 + } 692 + SAY("WARNING: failed to adjust hue: control not found\n"); 693 + return -ENOENT; 694 + } 695 + /*****************************************************************************/ 696 + int adjust_volume(struct easycap *peasycap, int value) 697 + { 698 + __s8 mood; 699 + int i1; 700 + 701 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 702 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 703 + return -EFAULT; 704 + } 705 + i1 = 0; 706 + while (0xFFFFFFFF != easycap_control[i1].id) { 707 + if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) { 708 + if ((easycap_control[i1].minimum > value) || \ 709 + (easycap_control[i1].maximum < value)) 710 + value = easycap_control[i1].default_value; 711 + peasycap->volume = value; 712 + mood = (16 > peasycap->volume) ? 16 : \ 713 + ((31 < peasycap->volume) ? 31 : \ 714 + (__s8) peasycap->volume); 715 + if (!audio_gainset(peasycap->pusb_device, mood)) { 716 + SAY("adjusting volume to 0x%01X\n", mood); 717 + return 0; 718 + } else { 719 + SAY("WARNING: failed to adjust volume to " \ 720 + "0x%1X\n", mood); 721 + return -ENOENT; 722 + } 723 + break; 724 + } 725 + i1++; 726 + } 727 + SAY("WARNING: failed to adjust volume: control not found\n"); 728 + return -ENOENT; 729 + } 730 + /*****************************************************************************/ 731 + /*---------------------------------------------------------------------------*/ 732 + /* 733 + * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE: 734 + * usb_set_interface(peasycap->pusb_device, \ 735 + * peasycap->audio_interface, \ 736 + * peasycap->audio_altsetting_off); 737 + * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS 738 + * -ESHUTDOWN. THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT 739 + * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE. 740 + */ 741 + /*---------------------------------------------------------------------------*/ 742 + int adjust_mute(struct easycap *peasycap, int value) 743 + { 744 + int i1; 745 + 746 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 747 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 748 + return -EFAULT; 749 + } 750 + i1 = 0; 751 + while (0xFFFFFFFF != easycap_control[i1].id) { 752 + if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) { 753 + peasycap->mute = value; 754 + switch (peasycap->mute) { 755 + case 1: { 756 + peasycap->audio_idle = 1; 757 + peasycap->timeval0.tv_sec = 0; 758 + SAY("adjusting mute: %i=peasycap->audio_idle\n", \ 759 + peasycap->audio_idle); 760 + return 0; 761 + } 762 + default: { 763 + peasycap->audio_idle = 0; 764 + SAY("adjusting mute: %i=peasycap->audio_idle\n", \ 765 + peasycap->audio_idle); 766 + return 0; 767 + } 768 + } 769 + break; 770 + } 771 + i1++; 772 + } 773 + SAY("WARNING: failed to adjust mute: control not found\n"); 774 + return -ENOENT; 775 + } 776 + /****************************************************************************/ 777 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 778 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 779 + long 780 + easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg)\ 781 + { 782 + return easycap_ioctl((struct inode *)NULL, file, cmd, arg); 783 + } 784 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 785 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 786 + /*--------------------------------------------------------------------------*/ 787 + int easycap_ioctl(struct inode *inode, struct file *file, \ 788 + unsigned int cmd, unsigned long arg) 789 + { 790 + static struct easycap *peasycap; 791 + static struct usb_device *p; 792 + static __u32 isequence; 793 + 794 + peasycap = (struct easycap *)file->private_data; 795 + if (NULL == peasycap) { 796 + SAY("ERROR: peasycap is NULL\n"); 797 + return -1; 798 + } 799 + p = peasycap->pusb_device; 800 + if ((struct usb_device *)NULL == p) { 801 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 802 + return -EFAULT; 803 + } 804 + /*---------------------------------------------------------------------------*/ 805 + /* 806 + * MOST OF THE VARIABLES DECLARED static IN THE case{} BLOCKS BELOW ARE SO 807 + * DECLARED SIMPLY TO AVOID A COMPILER WARNING OF THE KIND: 808 + * easycap_ioctl.c: warning: 809 + * the frame size of ... bytes is larger than 1024 bytes 810 + */ 811 + /*---------------------------------------------------------------------------*/ 812 + switch (cmd) { 813 + case VIDIOC_QUERYCAP: { 814 + static struct v4l2_capability v4l2_capability; 815 + static char version[16], *p1, *p2; 816 + static int i, rc, k[3]; 817 + static long lng; 818 + 819 + JOT(8, "VIDIOC_QUERYCAP\n"); 820 + 821 + if (16 <= strlen(EASYCAP_DRIVER_VERSION)) { 822 + SAY("ERROR: bad driver version string\n"); return -EINVAL; 823 + } 824 + strcpy(&version[0], EASYCAP_DRIVER_VERSION); 825 + for (i = 0; i < 3; i++) 826 + k[i] = 0; 827 + p2 = &version[0]; i = 0; 828 + while (*p2) { 829 + p1 = p2; 830 + while (*p2 && ('.' != *p2)) 831 + p2++; 832 + if (*p2) 833 + *p2++ = 0; 834 + if (3 > i) { 835 + rc = (int) strict_strtol(p1, 10, &lng); 836 + if (0 != rc) { 837 + SAY("ERROR: %i=strict_strtol(%s,.,,)\n", \ 838 + rc, p1); 839 + return -EINVAL; 840 + } 841 + k[i] = (int)lng; 842 + } 843 + i++; 844 + } 845 + 846 + memset(&v4l2_capability, 0, sizeof(struct v4l2_capability)); 847 + strlcpy(&v4l2_capability.driver[0], "easycap", \ 848 + sizeof(v4l2_capability.driver)); 849 + 850 + v4l2_capability.capabilities = \ 851 + V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \ 852 + V4L2_CAP_AUDIO | V4L2_CAP_READWRITE; 853 + 854 + v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]); 855 + JOT(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]); 856 + 857 + strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \ 858 + sizeof(v4l2_capability.card)); 859 + 860 + if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\ 861 + sizeof(v4l2_capability.bus_info)) < 0) { 862 + strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \ 863 + sizeof(v4l2_capability.bus_info)); 864 + JOT(8, "%s=v4l2_capability.bus_info\n", \ 865 + &v4l2_capability.bus_info[0]); 866 + } 867 + if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \ 868 + sizeof(struct v4l2_capability))) { 869 + POUT; 870 + return -EFAULT; 871 + } 872 + break; 873 + } 874 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 875 + case VIDIOC_ENUMINPUT: { 876 + static struct v4l2_input v4l2_input; 877 + static __u32 index; 878 + 879 + JOT(8, "VIDIOC_ENUMINPUT\n"); 880 + 881 + if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \ 882 + sizeof(struct v4l2_input))) { 883 + POUT; 884 + return -EFAULT; 885 + } 886 + 887 + index = v4l2_input.index; 888 + memset(&v4l2_input, 0, sizeof(struct v4l2_input)); 889 + 890 + switch (index) { 891 + case 0: { 892 + v4l2_input.index = index; 893 + strcpy(&v4l2_input.name[0], "CVBS0"); 894 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 895 + v4l2_input.audioset = 0x01; 896 + v4l2_input.tuner = 0; 897 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 898 + V4L2_STD_NTSC ; 899 + v4l2_input.status = 0; 900 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 901 + break; 902 + } 903 + case 1: { 904 + v4l2_input.index = index; 905 + strcpy(&v4l2_input.name[0], "CVBS1"); 906 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 907 + v4l2_input.audioset = 0x01; 908 + v4l2_input.tuner = 0; 909 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 910 + V4L2_STD_NTSC ; 911 + v4l2_input.status = 0; 912 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 913 + break; 914 + } 915 + case 2: { 916 + v4l2_input.index = index; 917 + strcpy(&v4l2_input.name[0], "CVBS2"); 918 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 919 + v4l2_input.audioset = 0x01; 920 + v4l2_input.tuner = 0; 921 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 922 + V4L2_STD_NTSC ; 923 + v4l2_input.status = 0; 924 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 925 + break; 926 + } 927 + case 3: { 928 + v4l2_input.index = index; 929 + strcpy(&v4l2_input.name[0], "CVBS3"); 930 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 931 + v4l2_input.audioset = 0x01; 932 + v4l2_input.tuner = 0; 933 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 934 + V4L2_STD_NTSC ; 935 + v4l2_input.status = 0; 936 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 937 + break; 938 + } 939 + case 4: { 940 + v4l2_input.index = index; 941 + strcpy(&v4l2_input.name[0], "CVBS4"); 942 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 943 + v4l2_input.audioset = 0x01; 944 + v4l2_input.tuner = 0; 945 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 946 + V4L2_STD_NTSC ; 947 + v4l2_input.status = 0; 948 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 949 + break; 950 + } 951 + case 5: { 952 + v4l2_input.index = index; 953 + strcpy(&v4l2_input.name[0], "S-VIDEO"); 954 + v4l2_input.type = V4L2_INPUT_TYPE_CAMERA; 955 + v4l2_input.audioset = 0x01; 956 + v4l2_input.tuner = 0; 957 + v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \ 958 + V4L2_STD_NTSC ; 959 + v4l2_input.status = 0; 960 + JOT(8, "%i=index: %s\n", index, &v4l2_input.name[0]); 961 + break; 962 + } 963 + default: { 964 + JOT(8, "%i=index: exhausts inputs\n", index); 965 + return -EINVAL; 966 + } 967 + } 968 + 969 + if (0 != copy_to_user((void __user *)arg, &v4l2_input, \ 970 + sizeof(struct v4l2_input))) { 971 + POUT; 972 + return -EFAULT; 973 + } 974 + break; 975 + } 976 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 977 + case VIDIOC_G_INPUT: { 978 + static __u32 index; 979 + 980 + JOT(8, "VIDIOC_G_INPUT\n"); 981 + index = (__u32)peasycap->input; 982 + JOT(8, "user is told: %i\n", index); 983 + if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) { 984 + POUT; 985 + return -EFAULT; 986 + } 987 + break; 988 + } 989 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 990 + case VIDIOC_S_INPUT: 991 + { 992 + static __u32 index; 993 + 994 + JOT(8, "VIDIOC_S_INPUT\n"); 995 + 996 + if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) { 997 + POUT; 998 + return -EFAULT; 999 + } 1000 + 1001 + JOT(8, "user requests input %i\n", index); 1002 + 1003 + if ((int)index == peasycap->input) { 1004 + SAY("requested input already in effect\n"); 1005 + break; 1006 + } 1007 + 1008 + if ((0 > index) || (5 < index)) { 1009 + JOT(8, "ERROR: bad requested input: %i\n", index); 1010 + return -EINVAL; 1011 + } 1012 + peasycap->input = (int)index; 1013 + 1014 + select_input(peasycap->pusb_device, peasycap->input, 9); 1015 + 1016 + break; 1017 + } 1018 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1019 + case VIDIOC_ENUMAUDIO: { 1020 + JOT(8, "VIDIOC_ENUMAUDIO\n"); 1021 + return -EINVAL; 1022 + } 1023 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1024 + case VIDIOC_ENUMAUDOUT: { 1025 + static struct v4l2_audioout v4l2_audioout; 1026 + 1027 + JOT(8, "VIDIOC_ENUMAUDOUT\n"); 1028 + 1029 + if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \ 1030 + sizeof(struct v4l2_audioout))) { 1031 + POUT; 1032 + return -EFAULT; 1033 + } 1034 + 1035 + if (0 != v4l2_audioout.index) 1036 + return -EINVAL; 1037 + memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout)); 1038 + v4l2_audioout.index = 0; 1039 + strcpy(&v4l2_audioout.name[0], "Soundtrack"); 1040 + 1041 + if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \ 1042 + sizeof(struct v4l2_audioout))) { 1043 + POUT; 1044 + return -EFAULT; 1045 + } 1046 + break; 1047 + } 1048 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1049 + case VIDIOC_QUERYCTRL: { 1050 + static int i1; 1051 + static struct v4l2_queryctrl v4l2_queryctrl; 1052 + 1053 + JOT(8, "VIDIOC_QUERYCTRL\n"); 1054 + 1055 + if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \ 1056 + sizeof(struct v4l2_queryctrl))) { 1057 + POUT; 1058 + return -EFAULT; 1059 + } 1060 + 1061 + i1 = 0; 1062 + while (0xFFFFFFFF != easycap_control[i1].id) { 1063 + if (easycap_control[i1].id == v4l2_queryctrl.id) { 1064 + JOT(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]" \ 1065 + ".name\n", &easycap_control[i1].name[0], i1); 1066 + memcpy(&v4l2_queryctrl, &easycap_control[i1], \ 1067 + sizeof(struct v4l2_queryctrl)); 1068 + break; 1069 + } 1070 + i1++; 1071 + } 1072 + if (0xFFFFFFFF == easycap_control[i1].id) { 1073 + JOT(8, "%i=index: exhausts controls\n", i1); 1074 + return -EINVAL; 1075 + } 1076 + if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \ 1077 + sizeof(struct v4l2_queryctrl))) { 1078 + POUT; 1079 + return -EFAULT; 1080 + } 1081 + break; 1082 + } 1083 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1084 + case VIDIOC_QUERYMENU: { 1085 + JOT(8, "VIDIOC_QUERYMENU unsupported\n"); 1086 + return -EINVAL; 1087 + break; 1088 + } 1089 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1090 + case VIDIOC_G_CTRL: { 1091 + static struct v4l2_control v4l2_control; 1092 + 1093 + JOT(8, "VIDIOC_G_CTRL\n"); 1094 + 1095 + if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ 1096 + sizeof(struct v4l2_control))) { 1097 + POUT; 1098 + return -EFAULT; 1099 + } 1100 + 1101 + switch (v4l2_control.id) { 1102 + case V4L2_CID_BRIGHTNESS: { 1103 + v4l2_control.value = peasycap->brightness; 1104 + JOT(8, "user enquires brightness: %i\n", v4l2_control.value); 1105 + break; 1106 + } 1107 + case V4L2_CID_CONTRAST: { 1108 + v4l2_control.value = peasycap->contrast; 1109 + JOT(8, "user enquires contrast: %i\n", v4l2_control.value); 1110 + break; 1111 + } 1112 + case V4L2_CID_SATURATION: { 1113 + v4l2_control.value = peasycap->saturation; 1114 + JOT(8, "user enquires saturation: %i\n", v4l2_control.value); 1115 + break; 1116 + } 1117 + case V4L2_CID_HUE: { 1118 + v4l2_control.value = peasycap->hue; 1119 + JOT(8, "user enquires hue: %i\n", v4l2_control.value); 1120 + break; 1121 + } 1122 + case V4L2_CID_AUDIO_VOLUME: { 1123 + v4l2_control.value = peasycap->volume; 1124 + JOT(8, "user enquires volume: %i\n", v4l2_control.value); 1125 + break; 1126 + } 1127 + case V4L2_CID_AUDIO_MUTE: { 1128 + if (1 == peasycap->mute) 1129 + v4l2_control.value = true; 1130 + else 1131 + v4l2_control.value = false; 1132 + JOT(8, "user enquires mute: %i\n", v4l2_control.value); 1133 + break; 1134 + } 1135 + default: { 1136 + SAY("ERROR: unknown V4L2 control: 0x%08X=id\n", \ 1137 + v4l2_control.id); 1138 + explain_cid(v4l2_control.id); 1139 + return -EINVAL; 1140 + } 1141 + } 1142 + if (0 != copy_to_user((void __user *)arg, &v4l2_control, \ 1143 + sizeof(struct v4l2_control))) { 1144 + POUT; 1145 + return -EFAULT; 1146 + } 1147 + break; 1148 + } 1149 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1150 + #if defined(VIDIOC_S_CTRL_OLD) 1151 + case VIDIOC_S_CTRL_OLD: { 1152 + JOT(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n"); 1153 + } 1154 + #endif /*VIDIOC_S_CTRL_OLD*/ 1155 + case VIDIOC_S_CTRL: 1156 + { 1157 + static struct v4l2_control v4l2_control; 1158 + 1159 + JOT(8, "VIDIOC_S_CTRL\n"); 1160 + 1161 + if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \ 1162 + sizeof(struct v4l2_control))) { 1163 + POUT; 1164 + return -EFAULT; 1165 + } 1166 + 1167 + switch (v4l2_control.id) { 1168 + case V4L2_CID_BRIGHTNESS: { 1169 + JOT(8, "user requests brightness %i\n", v4l2_control.value); 1170 + if (0 != adjust_brightness(peasycap, v4l2_control.value)) 1171 + ; 1172 + break; 1173 + } 1174 + case V4L2_CID_CONTRAST: { 1175 + JOT(8, "user requests contrast %i\n", v4l2_control.value); 1176 + if (0 != adjust_contrast(peasycap, v4l2_control.value)) 1177 + ; 1178 + break; 1179 + } 1180 + case V4L2_CID_SATURATION: { 1181 + JOT(8, "user requests saturation %i\n", v4l2_control.value); 1182 + if (0 != adjust_saturation(peasycap, v4l2_control.value)) 1183 + ; 1184 + break; 1185 + } 1186 + case V4L2_CID_HUE: { 1187 + JOT(8, "user requests hue %i\n", v4l2_control.value); 1188 + if (0 != adjust_hue(peasycap, v4l2_control.value)) 1189 + ; 1190 + break; 1191 + } 1192 + case V4L2_CID_AUDIO_VOLUME: { 1193 + JOT(8, "user requests volume %i\n", v4l2_control.value); 1194 + if (0 != adjust_volume(peasycap, v4l2_control.value)) 1195 + ; 1196 + break; 1197 + } 1198 + case V4L2_CID_AUDIO_MUTE: { 1199 + int mute; 1200 + 1201 + JOT(8, "user requests mute %i\n", v4l2_control.value); 1202 + if (true == v4l2_control.value) 1203 + mute = 1; 1204 + else 1205 + mute = 0; 1206 + 1207 + if (0 != adjust_mute(peasycap, mute)) 1208 + SAY("WARNING: failed to adjust mute to %i\n", mute); 1209 + break; 1210 + } 1211 + default: { 1212 + SAY("ERROR: unknown V4L2 control: 0x%08X=id\n", \ 1213 + v4l2_control.id); 1214 + explain_cid(v4l2_control.id); 1215 + return -EINVAL; 1216 + } 1217 + } 1218 + break; 1219 + } 1220 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1221 + case VIDIOC_S_EXT_CTRLS: { 1222 + JOT(8, "VIDIOC_S_EXT_CTRLS unsupported\n"); 1223 + return -EINVAL; 1224 + } 1225 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1226 + case VIDIOC_ENUM_FMT: { 1227 + static __u32 index; 1228 + static struct v4l2_fmtdesc v4l2_fmtdesc; 1229 + 1230 + JOT(8, "VIDIOC_ENUM_FMT\n"); 1231 + 1232 + if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \ 1233 + sizeof(struct v4l2_fmtdesc))) { 1234 + POUT; 1235 + return -EFAULT; 1236 + } 1237 + 1238 + index = v4l2_fmtdesc.index; 1239 + memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc)); 1240 + 1241 + v4l2_fmtdesc.index = index; 1242 + v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1243 + 1244 + switch (index) { 1245 + case 0: { 1246 + v4l2_fmtdesc.flags = 0; 1247 + strcpy(&v4l2_fmtdesc.description[0], "uyvy"); 1248 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY; 1249 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1250 + break; 1251 + } 1252 + case 1: { 1253 + v4l2_fmtdesc.flags = 0; 1254 + strcpy(&v4l2_fmtdesc.description[0], "yuy2"); 1255 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV; 1256 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1257 + break; 1258 + } 1259 + case 2: { 1260 + v4l2_fmtdesc.flags = 0; 1261 + strcpy(&v4l2_fmtdesc.description[0], "rgb24"); 1262 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24; 1263 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1264 + break; 1265 + } 1266 + case 3: { 1267 + v4l2_fmtdesc.flags = 0; 1268 + strcpy(&v4l2_fmtdesc.description[0], "rgb32"); 1269 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32; 1270 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1271 + break; 1272 + } 1273 + case 4: { 1274 + v4l2_fmtdesc.flags = 0; 1275 + strcpy(&v4l2_fmtdesc.description[0], "bgr24"); 1276 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24; 1277 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1278 + break; 1279 + } 1280 + case 5: { 1281 + v4l2_fmtdesc.flags = 0; 1282 + strcpy(&v4l2_fmtdesc.description[0], "bgr32"); 1283 + v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32; 1284 + JOT(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]); 1285 + break; 1286 + } 1287 + default: { 1288 + JOT(8, "%i=index: exhausts formats\n", index); 1289 + return -EINVAL; 1290 + } 1291 + } 1292 + if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \ 1293 + sizeof(struct v4l2_fmtdesc))) { 1294 + POUT; 1295 + return -EFAULT; 1296 + } 1297 + break; 1298 + } 1299 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1300 + case VIDIOC_ENUM_FRAMESIZES: { 1301 + JOT(8, "VIDIOC_ENUM_FRAMESIZES unsupported\n"); 1302 + return -EINVAL; 1303 + } 1304 + case VIDIOC_ENUM_FRAMEINTERVALS: { 1305 + JOT(8, "VIDIOC_ENUM_FRAME_INTERVALS unsupported\n"); 1306 + return -EINVAL; 1307 + } 1308 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1309 + case VIDIOC_G_FMT: { 1310 + static struct v4l2_format v4l2_format; 1311 + static struct v4l2_pix_format v4l2_pix_format; 1312 + 1313 + JOT(8, "VIDIOC_G_FMT\n"); 1314 + 1315 + if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ 1316 + sizeof(struct v4l2_format))) { 1317 + POUT; 1318 + return -EFAULT; 1319 + } 1320 + 1321 + if (v4l2_format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1322 + POUT; 1323 + return -EINVAL; 1324 + } 1325 + 1326 + memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); 1327 + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1328 + memcpy(&(v4l2_format.fmt.pix), \ 1329 + &(easycap_format[peasycap->format_offset]\ 1330 + .v4l2_format.fmt.pix), sizeof(v4l2_pix_format)); 1331 + JOT(8, "user is told: %s\n", \ 1332 + &easycap_format[peasycap->format_offset].name[0]); 1333 + 1334 + if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ 1335 + sizeof(struct v4l2_format))) { 1336 + POUT; 1337 + return -EFAULT; 1338 + } 1339 + break; 1340 + } 1341 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1342 + case VIDIOC_TRY_FMT: 1343 + case VIDIOC_S_FMT: { 1344 + static struct v4l2_format v4l2_format; 1345 + static struct v4l2_pix_format v4l2_pix_format; 1346 + static bool try; 1347 + static int best_format; 1348 + 1349 + if (VIDIOC_TRY_FMT == cmd) { 1350 + JOT(8, "VIDIOC_TRY_FMT\n"); 1351 + try = true; 1352 + } else { 1353 + JOT(8, "VIDIOC_S_FMT\n"); 1354 + try = false; 1355 + } 1356 + 1357 + if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \ 1358 + sizeof(struct v4l2_format))) { 1359 + POUT; 1360 + return -EFAULT; 1361 + } 1362 + 1363 + best_format = adjust_format(peasycap, \ 1364 + v4l2_format.fmt.pix.width, \ 1365 + v4l2_format.fmt.pix.height, \ 1366 + v4l2_format.fmt.pix.pixelformat, \ 1367 + v4l2_format.fmt.pix.field, \ 1368 + try); 1369 + if (0 > best_format) { 1370 + JOT(8, "WARNING: adjust_format() returned %i\n", best_format); 1371 + return -ENOENT; 1372 + } 1373 + /*...........................................................................*/ 1374 + memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format)); 1375 + v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1376 + 1377 + memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\ 1378 + .v4l2_format.fmt.pix), sizeof(v4l2_pix_format)); 1379 + JOT(8, "user is told: %s\n", &easycap_format[best_format].name[0]); 1380 + 1381 + if (0 != copy_to_user((void __user *)arg, &v4l2_format, \ 1382 + sizeof(struct v4l2_format))) { 1383 + POUT; 1384 + return -EFAULT; 1385 + } 1386 + break; 1387 + } 1388 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1389 + case VIDIOC_CROPCAP: { 1390 + static struct v4l2_cropcap v4l2_cropcap; 1391 + 1392 + JOT(8, "VIDIOC_CROPCAP\n"); 1393 + 1394 + if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \ 1395 + sizeof(struct v4l2_cropcap))) { 1396 + POUT; 1397 + return -EFAULT; 1398 + } 1399 + 1400 + if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1401 + JOT(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); 1402 + 1403 + memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap)); 1404 + v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1405 + v4l2_cropcap.bounds.left = 0; 1406 + v4l2_cropcap.bounds.top = 0; 1407 + v4l2_cropcap.bounds.width = peasycap->width; 1408 + v4l2_cropcap.bounds.height = peasycap->height; 1409 + v4l2_cropcap.defrect.left = 0; 1410 + v4l2_cropcap.defrect.top = 0; 1411 + v4l2_cropcap.defrect.width = peasycap->width; 1412 + v4l2_cropcap.defrect.height = peasycap->height; 1413 + v4l2_cropcap.pixelaspect.numerator = 1; 1414 + v4l2_cropcap.pixelaspect.denominator = 1; 1415 + 1416 + JOT(8, "user is told: %ix%i\n", peasycap->width, peasycap->height); 1417 + 1418 + if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \ 1419 + sizeof(struct v4l2_cropcap))) { 1420 + POUT; 1421 + return -EFAULT; 1422 + } 1423 + break; 1424 + } 1425 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1426 + case VIDIOC_G_CROP: 1427 + case VIDIOC_S_CROP: { 1428 + JOT(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n"); 1429 + return -EINVAL; 1430 + } 1431 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1432 + case VIDIOC_QUERYSTD: { 1433 + JOT(8, "VIDIOC_QUERYSTD: " \ 1434 + "EasyCAP is incapable of detecting standard\n"); 1435 + return -EINVAL; 1436 + break; 1437 + } 1438 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1439 + /*---------------------------------------------------------------------------*/ 1440 + /* 1441 + * THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND 1442 + * FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer. 1443 + * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer. 1444 + */ 1445 + /*---------------------------------------------------------------------------*/ 1446 + case VIDIOC_ENUMSTD: { 1447 + static int last0 = -1, last1 = -1, last2 = -1, last3 = -1; 1448 + static struct v4l2_standard v4l2_standard; 1449 + static __u32 index; 1450 + static struct easycap_standard *peasycap_standard; 1451 + 1452 + JOT(8, "VIDIOC_ENUMSTD\n"); 1453 + 1454 + if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \ 1455 + sizeof(struct v4l2_standard))) { 1456 + POUT; 1457 + return -EFAULT; 1458 + } 1459 + index = v4l2_standard.index; 1460 + 1461 + last3 = last2; last2 = last1; last1 = last0; last0 = index; 1462 + if ((index == last3) && (index == last2) && \ 1463 + (index == last1) && (index == last0)) { 1464 + index++; 1465 + last3 = last2; last2 = last1; last1 = last0; last0 = index; 1466 + } 1467 + 1468 + memset(&v4l2_standard, 0, sizeof(struct v4l2_standard)); 1469 + 1470 + peasycap_standard = &easycap_standard[0]; 1471 + while (0xFFFF != peasycap_standard->mask) { 1472 + if ((int)(peasycap_standard - &easycap_standard[0]) == index) 1473 + break; 1474 + peasycap_standard++; 1475 + } 1476 + if (0xFFFF == peasycap_standard->mask) { 1477 + JOT(8, "%i=index: exhausts standards\n", index); 1478 + return -EINVAL; 1479 + } 1480 + JOT(8, "%i=index: %s\n", index, \ 1481 + &(peasycap_standard->v4l2_standard.name[0])); 1482 + peasycap_standard->v4l2_standard.index = index; 1483 + v4l2_standard.index = index; 1484 + 1485 + if (0 != copy_to_user((void __user *)arg, \ 1486 + &(peasycap_standard->v4l2_standard), \ 1487 + sizeof(struct v4l2_standard))) { 1488 + POUT; 1489 + return -EFAULT; 1490 + } 1491 + break; 1492 + } 1493 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1494 + case VIDIOC_G_STD: { 1495 + static v4l2_std_id std_id; 1496 + static struct easycap_standard *peasycap_standard; 1497 + 1498 + JOT(8, "VIDIOC_G_STD\n"); 1499 + 1500 + if (0 != copy_from_user(&std_id, (void __user *)arg, \ 1501 + sizeof(v4l2_std_id))) { 1502 + POUT; 1503 + return -EFAULT; 1504 + } 1505 + 1506 + peasycap_standard = &easycap_standard[peasycap->standard_offset]; 1507 + std_id = peasycap_standard->v4l2_standard.id; 1508 + 1509 + JOT(8, "user is told: %s\n", \ 1510 + &peasycap_standard->v4l2_standard.name[0]); 1511 + 1512 + if (0 != copy_to_user((void __user *)arg, &std_id, \ 1513 + sizeof(v4l2_std_id))) { 1514 + POUT; 1515 + return -EFAULT; 1516 + } 1517 + break; 1518 + } 1519 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1520 + case VIDIOC_S_STD: { 1521 + static v4l2_std_id std_id; 1522 + static int rc; 1523 + 1524 + JOT(8, "VIDIOC_S_STD\n"); 1525 + 1526 + if (0 != copy_from_user(&std_id, (void __user *)arg, \ 1527 + sizeof(v4l2_std_id))) { 1528 + POUT; 1529 + return -EFAULT; 1530 + } 1531 + 1532 + rc = adjust_standard(peasycap, std_id); 1533 + if (0 > rc) { 1534 + JOT(8, "WARNING: adjust_standard() returned %i\n", rc); 1535 + return -ENOENT; 1536 + } 1537 + break; 1538 + } 1539 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1540 + case VIDIOC_REQBUFS: { 1541 + static int nbuffers; 1542 + static struct v4l2_requestbuffers v4l2_requestbuffers; 1543 + 1544 + JOT(8, "VIDIOC_REQBUFS\n"); 1545 + 1546 + if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \ 1547 + sizeof(struct v4l2_requestbuffers))) { 1548 + POUT; 1549 + return -EFAULT; 1550 + } 1551 + 1552 + if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1553 + return -EINVAL; 1554 + if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) { 1555 + POUT; 1556 + return -EINVAL; 1557 + } 1558 + nbuffers = v4l2_requestbuffers.count; 1559 + JOT(8, " User requests %i buffers ...\n", nbuffers); 1560 + if (nbuffers < 2) 1561 + nbuffers = 2; 1562 + if (nbuffers > FRAME_BUFFER_MANY) 1563 + nbuffers = FRAME_BUFFER_MANY; 1564 + if (v4l2_requestbuffers.count == nbuffers) { 1565 + JOT(8, " ... agree to %i buffers\n", \ 1566 + nbuffers); 1567 + } else { 1568 + JOT(8, " ... insist on %i buffers\n", \ 1569 + nbuffers); 1570 + v4l2_requestbuffers.count = nbuffers; 1571 + } 1572 + peasycap->frame_buffer_many = nbuffers; 1573 + 1574 + if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \ 1575 + sizeof(struct v4l2_requestbuffers))) { 1576 + POUT; 1577 + return -EFAULT; 1578 + } 1579 + break; 1580 + } 1581 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1582 + case VIDIOC_QUERYBUF: { 1583 + static __u32 index; 1584 + static struct v4l2_buffer v4l2_buffer; 1585 + 1586 + JOT(8, "VIDIOC_QUERYBUF\n"); 1587 + 1588 + if (peasycap->video_eof) { 1589 + JOT(8, "returning -1 because %i=video_eof\n", \ 1590 + peasycap->video_eof); 1591 + return -1; 1592 + } 1593 + 1594 + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 1595 + sizeof(struct v4l2_buffer))) { 1596 + POUT; 1597 + return -EFAULT; 1598 + } 1599 + 1600 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1601 + return -EINVAL; 1602 + index = v4l2_buffer.index; 1603 + if (index < 0 || index >= peasycap->frame_buffer_many) 1604 + return -EINVAL; 1605 + memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer)); 1606 + v4l2_buffer.index = index; 1607 + v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1608 + v4l2_buffer.bytesused = peasycap->frame_buffer_used; 1609 + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \ 1610 + peasycap->done[index] | \ 1611 + peasycap->queued[index]; 1612 + v4l2_buffer.field = peasycap->field; 1613 + v4l2_buffer.memory = V4L2_MEMORY_MMAP; 1614 + v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE; 1615 + v4l2_buffer.length = FRAME_BUFFER_SIZE; 1616 + 1617 + JOT(16, " %10i=index\n", v4l2_buffer.index); 1618 + JOT(16, " 0x%08X=type\n", v4l2_buffer.type); 1619 + JOT(16, " %10i=bytesused\n", v4l2_buffer.bytesused); 1620 + JOT(16, " 0x%08X=flags\n", v4l2_buffer.flags); 1621 + JOT(16, " %10i=field\n", v4l2_buffer.field); 1622 + JOT(16, " %10li=timestamp.tv_usec\n", \ 1623 + (long)v4l2_buffer.timestamp.tv_usec); 1624 + JOT(16, " %10i=sequence\n", v4l2_buffer.sequence); 1625 + JOT(16, " 0x%08X=memory\n", v4l2_buffer.memory); 1626 + JOT(16, " %10i=m.offset\n", v4l2_buffer.m.offset); 1627 + JOT(16, " %10i=length\n", v4l2_buffer.length); 1628 + 1629 + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 1630 + sizeof(struct v4l2_buffer))) { 1631 + POUT; 1632 + return -EFAULT; 1633 + } 1634 + break; 1635 + } 1636 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1637 + case VIDIOC_QBUF: { 1638 + static struct v4l2_buffer v4l2_buffer; 1639 + 1640 + JOT(8, "VIDIOC_QBUF\n"); 1641 + 1642 + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 1643 + sizeof(struct v4l2_buffer))) { 1644 + POUT; 1645 + return -EFAULT; 1646 + } 1647 + 1648 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1649 + return -EINVAL; 1650 + if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) 1651 + return -EINVAL; 1652 + if (v4l2_buffer.index < 0 || \ 1653 + (v4l2_buffer.index >= peasycap->frame_buffer_many)) 1654 + return -EINVAL; 1655 + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED; 1656 + 1657 + peasycap->done[v4l2_buffer.index] = 0; 1658 + peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED; 1659 + 1660 + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 1661 + sizeof(struct v4l2_buffer))) { 1662 + POUT; 1663 + return -EFAULT; 1664 + } 1665 + 1666 + JOT(8, "..... user queueing frame buffer %i\n", \ 1667 + (int)v4l2_buffer.index); 1668 + 1669 + peasycap->frame_lock = 0; 1670 + 1671 + break; 1672 + } 1673 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1674 + case VIDIOC_DQBUF: 1675 + { 1676 + #if defined(AUDIOTIME) 1677 + static struct signed_div_result sdr; 1678 + static long long int above, below, dnbydt, fudge, sll; 1679 + static unsigned long long int ull; 1680 + static struct timeval timeval0; 1681 + struct timeval timeval1; 1682 + #endif /*AUDIOTIME*/ 1683 + static struct timeval timeval, timeval2; 1684 + static int i, j; 1685 + static struct v4l2_buffer v4l2_buffer; 1686 + 1687 + JOT(8, "VIDIOC_DQBUF\n"); 1688 + 1689 + if ((peasycap->video_idle) || (peasycap->video_eof)) { 1690 + JOT(8, "returning -EIO because " \ 1691 + "%i=video_idle %i=video_eof\n", \ 1692 + peasycap->video_idle, peasycap->video_eof); 1693 + return -EIO; 1694 + } 1695 + 1696 + if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \ 1697 + sizeof(struct v4l2_buffer))) { 1698 + POUT; 1699 + return -EFAULT; 1700 + } 1701 + 1702 + if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) 1703 + return -EINVAL; 1704 + 1705 + if (!peasycap->video_isoc_streaming) { 1706 + JOT(16, "returning -EIO because video urbs not streaming\n"); 1707 + return -EIO; 1708 + } 1709 + /*---------------------------------------------------------------------------*/ 1710 + /* 1711 + * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING 1712 + * THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE. IN THIS 1713 + * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read 1714 + */ 1715 + /*---------------------------------------------------------------------------*/ 1716 + 1717 + if (!peasycap->polled) { 1718 + if (-EIO == easycap_dqbuf(peasycap, 0)) 1719 + return -EIO; 1720 + } else { 1721 + if (peasycap->video_eof) 1722 + return -EIO; 1723 + } 1724 + if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) { 1725 + SAY("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \ 1726 + peasycap->done[peasycap->frame_read]); 1727 + } 1728 + peasycap->polled = 0; 1729 + 1730 + if (!(isequence % 10)) { 1731 + for (i = 0; i < 179; i++) 1732 + peasycap->merit[i] = peasycap->merit[i+1]; 1733 + peasycap->merit[179] = merit_saa(peasycap->pusb_device); 1734 + j = 0; 1735 + for (i = 0; i < 180; i++) 1736 + j += peasycap->merit[i]; 1737 + if (90 < j) { 1738 + SAY("easycap driver shutting down " \ 1739 + "on condition blue\n"); 1740 + peasycap->video_eof = 1; peasycap->audio_eof = 1; 1741 + } 1742 + } 1743 + 1744 + v4l2_buffer.index = peasycap->frame_read; 1745 + v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 1746 + v4l2_buffer.bytesused = peasycap->frame_buffer_used; 1747 + v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE; 1748 + v4l2_buffer.field = peasycap->field; 1749 + if (V4L2_FIELD_ALTERNATE == v4l2_buffer.field) 1750 + v4l2_buffer.field = \ 1751 + 0x000F & (peasycap->\ 1752 + frame_buffer[peasycap->frame_read][0].kount); 1753 + do_gettimeofday(&timeval); 1754 + timeval2 = timeval; 1755 + 1756 + #if defined(AUDIOTIME) 1757 + if (!peasycap->timeval0.tv_sec) { 1758 + timeval0 = timeval; 1759 + timeval1 = timeval; 1760 + timeval2 = timeval; 1761 + dnbydt = 192000; 1762 + 1763 + if (mutex_lock_interruptible(&(peasycap->mutex_timeval0))) 1764 + return -ERESTARTSYS; 1765 + peasycap->timeval0 = timeval0; 1766 + mutex_unlock(&(peasycap->mutex_timeval0)); 1767 + } else { 1768 + if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) 1769 + return -ERESTARTSYS; 1770 + dnbydt = peasycap->dnbydt; 1771 + timeval1 = peasycap->timeval1; 1772 + mutex_unlock(&(peasycap->mutex_timeval1)); 1773 + above = dnbydt * MICROSECONDS(timeval, timeval1); 1774 + below = 192000; 1775 + sdr = signed_div(above, below); 1776 + 1777 + above = sdr.quotient + timeval1.tv_usec - 350000; 1778 + 1779 + below = 1000000; 1780 + sdr = signed_div(above, below); 1781 + timeval2.tv_usec = sdr.remainder; 1782 + timeval2.tv_sec = timeval1.tv_sec + sdr.quotient; 1783 + } 1784 + if (!(isequence % 500)) { 1785 + fudge = ((long long int)(1000000)) * \ 1786 + ((long long int)(timeval.tv_sec - \ 1787 + timeval2.tv_sec)) + \ 1788 + (long long int)(timeval.tv_usec - \ 1789 + timeval2.tv_usec); 1790 + sdr = signed_div(fudge, 1000); 1791 + sll = sdr.quotient; 1792 + ull = sdr.remainder; 1793 + 1794 + SAY("%5lli.%-3lli=ms timestamp fudge\n", sll, ull); 1795 + } 1796 + #endif /*AUDIOTIME*/ 1797 + 1798 + v4l2_buffer.timestamp = timeval2; 1799 + v4l2_buffer.sequence = isequence++; 1800 + v4l2_buffer.memory = V4L2_MEMORY_MMAP; 1801 + v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE; 1802 + v4l2_buffer.length = FRAME_BUFFER_SIZE; 1803 + 1804 + JOT(16, " %10i=index\n", v4l2_buffer.index); 1805 + JOT(16, " 0x%08X=type\n", v4l2_buffer.type); 1806 + JOT(16, " %10i=bytesused\n", v4l2_buffer.bytesused); 1807 + JOT(16, " 0x%08X=flags\n", v4l2_buffer.flags); 1808 + JOT(16, " %10i=field\n", v4l2_buffer.field); 1809 + JOT(16, " %10li=timestamp.tv_usec\n", \ 1810 + (long)v4l2_buffer.timestamp.tv_usec); 1811 + JOT(16, " %10i=sequence\n", v4l2_buffer.sequence); 1812 + JOT(16, " 0x%08X=memory\n", v4l2_buffer.memory); 1813 + JOT(16, " %10i=m.offset\n", v4l2_buffer.m.offset); 1814 + JOT(16, " %10i=length\n", v4l2_buffer.length); 1815 + 1816 + if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \ 1817 + sizeof(struct v4l2_buffer))) { 1818 + POUT; 1819 + return -EFAULT; 1820 + } 1821 + 1822 + JOT(8, "..... user is offered frame buffer %i\n", \ 1823 + peasycap->frame_read); 1824 + peasycap->frame_lock = 1; 1825 + if (peasycap->frame_read == peasycap->frame_fill) { 1826 + if (peasycap->frame_lock) { 1827 + JOT(8, "ERROR: filling frame buffer " \ 1828 + "while offered to user\n"); 1829 + } 1830 + } 1831 + break; 1832 + } 1833 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1834 + /*---------------------------------------------------------------------------*/ 1835 + /* 1836 + * AUDIO URBS HAVE ALREADY BEEN SUBMITTED WHEN THIS COMMAND IS RECEIVED; 1837 + * VIDEO URBS HAVE NOT. 1838 + */ 1839 + /*---------------------------------------------------------------------------*/ 1840 + case VIDIOC_STREAMON: { 1841 + static int i; 1842 + 1843 + JOT(8, "VIDIOC_STREAMON\n"); 1844 + 1845 + isequence = 0; 1846 + for (i = 0; i < 180; i++) 1847 + peasycap->merit[i] = 0; 1848 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 1849 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 1850 + return -EFAULT; 1851 + } 1852 + submit_video_urbs(peasycap); 1853 + peasycap->video_idle = 0; 1854 + peasycap->audio_idle = 0; 1855 + peasycap->video_eof = 0; 1856 + peasycap->audio_eof = 0; 1857 + break; 1858 + } 1859 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1860 + case VIDIOC_STREAMOFF: { 1861 + JOT(8, "VIDIOC_STREAMOFF\n"); 1862 + 1863 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 1864 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 1865 + return -EFAULT; 1866 + } 1867 + 1868 + peasycap->video_idle = 1; 1869 + peasycap->audio_idle = 1; peasycap->timeval0.tv_sec = 0; 1870 + /*---------------------------------------------------------------------------*/ 1871 + /* 1872 + * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND 1873 + * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. 1874 + */ 1875 + /*---------------------------------------------------------------------------*/ 1876 + JOT(8, "calling wake_up on wq_video and wq_audio\n"); 1877 + wake_up_interruptible(&(peasycap->wq_video)); 1878 + wake_up_interruptible(&(peasycap->wq_audio)); 1879 + /*---------------------------------------------------------------------------*/ 1880 + break; 1881 + } 1882 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1883 + case VIDIOC_G_PARM: { 1884 + static struct v4l2_streamparm v4l2_streamparm; 1885 + 1886 + JOT(8, "VIDIOC_G_PARM\n"); 1887 + 1888 + if (0 != copy_from_user(&v4l2_streamparm, (void __user *)arg, \ 1889 + sizeof(struct v4l2_streamparm))) { 1890 + POUT; 1891 + return -EFAULT; 1892 + } 1893 + 1894 + if (v4l2_streamparm.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { 1895 + POUT; 1896 + return -EINVAL; 1897 + } 1898 + v4l2_streamparm.parm.capture.capability = 0; 1899 + v4l2_streamparm.parm.capture.capturemode = 0; 1900 + v4l2_streamparm.parm.capture.timeperframe.numerator = 1; 1901 + v4l2_streamparm.parm.capture.timeperframe.denominator = 30; 1902 + v4l2_streamparm.parm.capture.readbuffers = peasycap->frame_buffer_many; 1903 + v4l2_streamparm.parm.capture.extendedmode = 0; 1904 + if (0 != copy_to_user((void __user *)arg, &v4l2_streamparm, \ 1905 + sizeof(struct v4l2_streamparm))) { 1906 + POUT; 1907 + return -EFAULT; 1908 + } 1909 + break; 1910 + } 1911 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1912 + case VIDIOC_S_PARM: { 1913 + JOT(8, "VIDIOC_S_PARM unsupported\n"); 1914 + return -EINVAL; 1915 + } 1916 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1917 + case VIDIOC_G_AUDIO: { 1918 + JOT(8, "VIDIOC_G_AUDIO unsupported\n"); 1919 + return -EINVAL; 1920 + } 1921 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1922 + case VIDIOC_S_AUDIO: { 1923 + JOT(8, "VIDIOC_S_AUDIO unsupported\n"); 1924 + return -EINVAL; 1925 + } 1926 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1927 + case VIDIOC_S_TUNER: { 1928 + JOT(8, "VIDIOC_S_TUNER unsupported\n"); 1929 + return -EINVAL; 1930 + } 1931 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1932 + case VIDIOC_G_FBUF: 1933 + case VIDIOC_S_FBUF: 1934 + case VIDIOC_OVERLAY: { 1935 + JOT(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n"); 1936 + return -EINVAL; 1937 + } 1938 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1939 + case VIDIOC_G_TUNER: { 1940 + JOT(8, "VIDIOC_G_TUNER unsupported\n"); 1941 + return -EINVAL; 1942 + } 1943 + case VIDIOC_G_FREQUENCY: 1944 + case VIDIOC_S_FREQUENCY: { 1945 + JOT(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n"); 1946 + return -EINVAL; 1947 + } 1948 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1949 + default: { 1950 + JOT(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd); 1951 + explain_ioctl(cmd); 1952 + POUT; 1953 + return -ENOIOCTLCMD; 1954 + } 1955 + } 1956 + return 0; 1957 + } 1958 + /****************************************************************************/ 1959 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 1960 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 1961 + long 1962 + easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) 1963 + { 1964 + return easysnd_ioctl((struct inode *)NULL, file, cmd, arg); 1965 + } 1966 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 1967 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 1968 + /*--------------------------------------------------------------------------*/ 1969 + int easysnd_ioctl(struct inode *inode, struct file *file, \ 1970 + unsigned int cmd, unsigned long arg) 1971 + { 1972 + struct easycap *peasycap; 1973 + struct usb_device *p; 1974 + 1975 + peasycap = (struct easycap *)file->private_data; 1976 + if (NULL == peasycap) { 1977 + SAY("ERROR: peasycap is NULL.\n"); 1978 + return -1; 1979 + } 1980 + p = peasycap->pusb_device; 1981 + /*---------------------------------------------------------------------------*/ 1982 + switch (cmd) { 1983 + case SNDCTL_DSP_GETCAPS: { 1984 + int caps; 1985 + JOT(8, "SNDCTL_DSP_GETCAPS\n"); 1986 + 1987 + if (true == peasycap->microphone) 1988 + caps = 0x02400000; 1989 + else 1990 + caps = 0x04400000; 1991 + 1992 + if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) 1993 + return -EFAULT; 1994 + break; 1995 + } 1996 + case SNDCTL_DSP_GETFMTS: { 1997 + int incoming; 1998 + JOT(8, "SNDCTL_DSP_GETFMTS\n"); 1999 + 2000 + if (true == peasycap->microphone) 2001 + incoming = AFMT_S16_LE; 2002 + else 2003 + incoming = AFMT_S16_LE; 2004 + 2005 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2006 + return -EFAULT; 2007 + break; 2008 + } 2009 + case SNDCTL_DSP_SETFMT: { 2010 + int incoming, outgoing; 2011 + JOT(8, "SNDCTL_DSP_SETFMT\n"); 2012 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2013 + return -EFAULT; 2014 + JOT(8, "........... %i=incoming\n", incoming); 2015 + 2016 + if (true == peasycap->microphone) 2017 + outgoing = AFMT_S16_LE; 2018 + else 2019 + outgoing = AFMT_S16_LE; 2020 + 2021 + if (incoming != outgoing) { 2022 + JOT(8, "........... %i=outgoing\n", outgoing); 2023 + JOT(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE); 2024 + JOT(8, " cf. %i=AFMT_U8\n", AFMT_U8); 2025 + if (0 != copy_to_user((void __user *)arg, &outgoing, \ 2026 + sizeof(int))) 2027 + return -EFAULT; 2028 + return -EINVAL ; 2029 + } 2030 + break; 2031 + } 2032 + case SNDCTL_DSP_STEREO: { 2033 + int incoming; 2034 + JOT(8, "SNDCTL_DSP_STEREO\n"); 2035 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2036 + return -EFAULT; 2037 + JOT(8, "........... %i=incoming\n", incoming); 2038 + 2039 + if (true == peasycap->microphone) 2040 + incoming = 0; 2041 + else 2042 + incoming = 1; 2043 + 2044 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2045 + return -EFAULT; 2046 + break; 2047 + } 2048 + case SNDCTL_DSP_SPEED: { 2049 + int incoming; 2050 + JOT(8, "SNDCTL_DSP_SPEED\n"); 2051 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2052 + return -EFAULT; 2053 + JOT(8, "........... %i=incoming\n", incoming); 2054 + 2055 + if (true == peasycap->microphone) 2056 + incoming = 8000; 2057 + else 2058 + incoming = 48000; 2059 + 2060 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2061 + return -EFAULT; 2062 + break; 2063 + } 2064 + case SNDCTL_DSP_GETTRIGGER: { 2065 + int incoming; 2066 + JOT(8, "SNDCTL_DSP_GETTRIGGER\n"); 2067 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2068 + return -EFAULT; 2069 + JOT(8, "........... %i=incoming\n", incoming); 2070 + 2071 + incoming = PCM_ENABLE_INPUT; 2072 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2073 + return -EFAULT; 2074 + break; 2075 + } 2076 + case SNDCTL_DSP_SETTRIGGER: { 2077 + int incoming; 2078 + JOT(8, "SNDCTL_DSP_SETTRIGGER\n"); 2079 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2080 + return -EFAULT; 2081 + JOT(8, "........... %i=incoming\n", incoming); 2082 + JOT(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \ 2083 + "0x%x=PCM_ENABLE_OUTPUT\n", \ 2084 + PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT); 2085 + ; 2086 + ; 2087 + ; 2088 + ; 2089 + break; 2090 + } 2091 + case SNDCTL_DSP_GETBLKSIZE: { 2092 + int incoming; 2093 + JOT(8, "SNDCTL_DSP_GETBLKSIZE\n"); 2094 + if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) 2095 + return -EFAULT; 2096 + JOT(8, "........... %i=incoming\n", incoming); 2097 + incoming = audio_bytes_per_fragment; 2098 + if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) 2099 + return -EFAULT; 2100 + break; 2101 + } 2102 + case SNDCTL_DSP_GETISPACE: { 2103 + struct audio_buf_info audio_buf_info; 2104 + 2105 + JOT(8, "SNDCTL_DSP_GETISPACE\n"); 2106 + 2107 + audio_buf_info.bytes = audio_bytes_per_fragment; 2108 + audio_buf_info.fragments = 1; 2109 + audio_buf_info.fragsize = 0; 2110 + audio_buf_info.fragstotal = 0; 2111 + 2112 + if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \ 2113 + sizeof(int))) 2114 + return -EFAULT; 2115 + break; 2116 + } 2117 + default: { 2118 + JOT(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd); 2119 + POUT; 2120 + return -ENOIOCTLCMD; 2121 + } 2122 + } 2123 + return 0; 2124 + } 2125 + /*****************************************************************************/ 2126 + int explain_ioctl(__u32 wot) 2127 + { 2128 + int k; 2129 + /*---------------------------------------------------------------------------*/ 2130 + /* 2131 + * THE DATA FOR THE ARRAY mess BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING 2132 + * SHELL SCRIPT: 2133 + * # 2134 + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev2.h | \ 2135 + * grep "^#define VIDIOC_" - | grep -v "_OLD" - | \ 2136 + * sed -e "s,_IO.*$,,;p" | sed -e "N;s,\n,, " | \ 2137 + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ 2138 + * sed -e "s, ,,g;s, ,,g" >ioctl.tmp 2139 + * echo "{0xFFFFFFFF,\"\"}" >>ioctl.tmp 2140 + * exit 0 2141 + * # 2142 + * AND REINSTATING THE EXCISED "_OLD" CASES WERE LATER MANUALLY. 2143 + * 2144 + * THE DATA FOR THE ARRAY mess1 BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING 2145 + * SHELL SCRIPT: 2146 + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev.h | \ 2147 + * grep "^#define VIDIOC" - | grep -v "_OLD" - | \ 2148 + * sed -e "s,_IO.*$,,;p" | sed -e "N;s,\n,, " | \ 2149 + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ 2150 + * sed -e "s, ,,g;s, ,,g" >ioctl.tmp 2151 + * echo "{0xFFFFFFFF,\"\"}" >>ioctl.tmp 2152 + * exit 0 2153 + * # 2154 + */ 2155 + /*---------------------------------------------------------------------------*/ 2156 + static struct mess { 2157 + __u32 command; 2158 + char name[64]; 2159 + } mess[] = { 2160 + #if defined(VIDIOC_QUERYCAP) 2161 + {VIDIOC_QUERYCAP, "VIDIOC_QUERYCAP"}, 2162 + #endif 2163 + #if defined(VIDIOC_RESERVED) 2164 + {VIDIOC_RESERVED, "VIDIOC_RESERVED"}, 2165 + #endif 2166 + #if defined(VIDIOC_ENUM_FMT) 2167 + {VIDIOC_ENUM_FMT, "VIDIOC_ENUM_FMT"}, 2168 + #endif 2169 + #if defined(VIDIOC_G_FMT) 2170 + {VIDIOC_G_FMT, "VIDIOC_G_FMT"}, 2171 + #endif 2172 + #if defined(VIDIOC_S_FMT) 2173 + {VIDIOC_S_FMT, "VIDIOC_S_FMT"}, 2174 + #endif 2175 + #if defined(VIDIOC_REQBUFS) 2176 + {VIDIOC_REQBUFS, "VIDIOC_REQBUFS"}, 2177 + #endif 2178 + #if defined(VIDIOC_QUERYBUF) 2179 + {VIDIOC_QUERYBUF, "VIDIOC_QUERYBUF"}, 2180 + #endif 2181 + #if defined(VIDIOC_G_FBUF) 2182 + {VIDIOC_G_FBUF, "VIDIOC_G_FBUF"}, 2183 + #endif 2184 + #if defined(VIDIOC_S_FBUF) 2185 + {VIDIOC_S_FBUF, "VIDIOC_S_FBUF"}, 2186 + #endif 2187 + #if defined(VIDIOC_OVERLAY) 2188 + {VIDIOC_OVERLAY, "VIDIOC_OVERLAY"}, 2189 + #endif 2190 + #if defined(VIDIOC_QBUF) 2191 + {VIDIOC_QBUF, "VIDIOC_QBUF"}, 2192 + #endif 2193 + #if defined(VIDIOC_DQBUF) 2194 + {VIDIOC_DQBUF, "VIDIOC_DQBUF"}, 2195 + #endif 2196 + #if defined(VIDIOC_STREAMON) 2197 + {VIDIOC_STREAMON, "VIDIOC_STREAMON"}, 2198 + #endif 2199 + #if defined(VIDIOC_STREAMOFF) 2200 + {VIDIOC_STREAMOFF, "VIDIOC_STREAMOFF"}, 2201 + #endif 2202 + #if defined(VIDIOC_G_PARM) 2203 + {VIDIOC_G_PARM, "VIDIOC_G_PARM"}, 2204 + #endif 2205 + #if defined(VIDIOC_S_PARM) 2206 + {VIDIOC_S_PARM, "VIDIOC_S_PARM"}, 2207 + #endif 2208 + #if defined(VIDIOC_G_STD) 2209 + {VIDIOC_G_STD, "VIDIOC_G_STD"}, 2210 + #endif 2211 + #if defined(VIDIOC_S_STD) 2212 + {VIDIOC_S_STD, "VIDIOC_S_STD"}, 2213 + #endif 2214 + #if defined(VIDIOC_ENUMSTD) 2215 + {VIDIOC_ENUMSTD, "VIDIOC_ENUMSTD"}, 2216 + #endif 2217 + #if defined(VIDIOC_ENUMINPUT) 2218 + {VIDIOC_ENUMINPUT, "VIDIOC_ENUMINPUT"}, 2219 + #endif 2220 + #if defined(VIDIOC_G_CTRL) 2221 + {VIDIOC_G_CTRL, "VIDIOC_G_CTRL"}, 2222 + #endif 2223 + #if defined(VIDIOC_S_CTRL) 2224 + {VIDIOC_S_CTRL, "VIDIOC_S_CTRL"}, 2225 + #endif 2226 + #if defined(VIDIOC_G_TUNER) 2227 + {VIDIOC_G_TUNER, "VIDIOC_G_TUNER"}, 2228 + #endif 2229 + #if defined(VIDIOC_S_TUNER) 2230 + {VIDIOC_S_TUNER, "VIDIOC_S_TUNER"}, 2231 + #endif 2232 + #if defined(VIDIOC_G_AUDIO) 2233 + {VIDIOC_G_AUDIO, "VIDIOC_G_AUDIO"}, 2234 + #endif 2235 + #if defined(VIDIOC_S_AUDIO) 2236 + {VIDIOC_S_AUDIO, "VIDIOC_S_AUDIO"}, 2237 + #endif 2238 + #if defined(VIDIOC_QUERYCTRL) 2239 + {VIDIOC_QUERYCTRL, "VIDIOC_QUERYCTRL"}, 2240 + #endif 2241 + #if defined(VIDIOC_QUERYMENU) 2242 + {VIDIOC_QUERYMENU, "VIDIOC_QUERYMENU"}, 2243 + #endif 2244 + #if defined(VIDIOC_G_INPUT) 2245 + {VIDIOC_G_INPUT, "VIDIOC_G_INPUT"}, 2246 + #endif 2247 + #if defined(VIDIOC_S_INPUT) 2248 + {VIDIOC_S_INPUT, "VIDIOC_S_INPUT"}, 2249 + #endif 2250 + #if defined(VIDIOC_G_OUTPUT) 2251 + {VIDIOC_G_OUTPUT, "VIDIOC_G_OUTPUT"}, 2252 + #endif 2253 + #if defined(VIDIOC_S_OUTPUT) 2254 + {VIDIOC_S_OUTPUT, "VIDIOC_S_OUTPUT"}, 2255 + #endif 2256 + #if defined(VIDIOC_ENUMOUTPUT) 2257 + {VIDIOC_ENUMOUTPUT, "VIDIOC_ENUMOUTPUT"}, 2258 + #endif 2259 + #if defined(VIDIOC_G_AUDOUT) 2260 + {VIDIOC_G_AUDOUT, "VIDIOC_G_AUDOUT"}, 2261 + #endif 2262 + #if defined(VIDIOC_S_AUDOUT) 2263 + {VIDIOC_S_AUDOUT, "VIDIOC_S_AUDOUT"}, 2264 + #endif 2265 + #if defined(VIDIOC_G_MODULATOR) 2266 + {VIDIOC_G_MODULATOR, "VIDIOC_G_MODULATOR"}, 2267 + #endif 2268 + #if defined(VIDIOC_S_MODULATOR) 2269 + {VIDIOC_S_MODULATOR, "VIDIOC_S_MODULATOR"}, 2270 + #endif 2271 + #if defined(VIDIOC_G_FREQUENCY) 2272 + {VIDIOC_G_FREQUENCY, "VIDIOC_G_FREQUENCY"}, 2273 + #endif 2274 + #if defined(VIDIOC_S_FREQUENCY) 2275 + {VIDIOC_S_FREQUENCY, "VIDIOC_S_FREQUENCY"}, 2276 + #endif 2277 + #if defined(VIDIOC_CROPCAP) 2278 + {VIDIOC_CROPCAP, "VIDIOC_CROPCAP"}, 2279 + #endif 2280 + #if defined(VIDIOC_G_CROP) 2281 + {VIDIOC_G_CROP, "VIDIOC_G_CROP"}, 2282 + #endif 2283 + #if defined(VIDIOC_S_CROP) 2284 + {VIDIOC_S_CROP, "VIDIOC_S_CROP"}, 2285 + #endif 2286 + #if defined(VIDIOC_G_JPEGCOMP) 2287 + {VIDIOC_G_JPEGCOMP, "VIDIOC_G_JPEGCOMP"}, 2288 + #endif 2289 + #if defined(VIDIOC_S_JPEGCOMP) 2290 + {VIDIOC_S_JPEGCOMP, "VIDIOC_S_JPEGCOMP"}, 2291 + #endif 2292 + #if defined(VIDIOC_QUERYSTD) 2293 + {VIDIOC_QUERYSTD, "VIDIOC_QUERYSTD"}, 2294 + #endif 2295 + #if defined(VIDIOC_TRY_FMT) 2296 + {VIDIOC_TRY_FMT, "VIDIOC_TRY_FMT"}, 2297 + #endif 2298 + #if defined(VIDIOC_ENUMAUDIO) 2299 + {VIDIOC_ENUMAUDIO, "VIDIOC_ENUMAUDIO"}, 2300 + #endif 2301 + #if defined(VIDIOC_ENUMAUDOUT) 2302 + {VIDIOC_ENUMAUDOUT, "VIDIOC_ENUMAUDOUT"}, 2303 + #endif 2304 + #if defined(VIDIOC_G_PRIORITY) 2305 + {VIDIOC_G_PRIORITY, "VIDIOC_G_PRIORITY"}, 2306 + #endif 2307 + #if defined(VIDIOC_S_PRIORITY) 2308 + {VIDIOC_S_PRIORITY, "VIDIOC_S_PRIORITY"}, 2309 + #endif 2310 + #if defined(VIDIOC_G_SLICED_VBI_CAP) 2311 + {VIDIOC_G_SLICED_VBI_CAP, "VIDIOC_G_SLICED_VBI_CAP"}, 2312 + #endif 2313 + #if defined(VIDIOC_LOG_STATUS) 2314 + {VIDIOC_LOG_STATUS, "VIDIOC_LOG_STATUS"}, 2315 + #endif 2316 + #if defined(VIDIOC_G_EXT_CTRLS) 2317 + {VIDIOC_G_EXT_CTRLS, "VIDIOC_G_EXT_CTRLS"}, 2318 + #endif 2319 + #if defined(VIDIOC_S_EXT_CTRLS) 2320 + {VIDIOC_S_EXT_CTRLS, "VIDIOC_S_EXT_CTRLS"}, 2321 + #endif 2322 + #if defined(VIDIOC_TRY_EXT_CTRLS) 2323 + {VIDIOC_TRY_EXT_CTRLS, "VIDIOC_TRY_EXT_CTRLS"}, 2324 + #endif 2325 + #if defined(VIDIOC_ENUM_FRAMESIZES) 2326 + {VIDIOC_ENUM_FRAMESIZES, "VIDIOC_ENUM_FRAMESIZES"}, 2327 + #endif 2328 + #if defined(VIDIOC_ENUM_FRAMEINTERVALS) 2329 + {VIDIOC_ENUM_FRAMEINTERVALS, "VIDIOC_ENUM_FRAMEINTERVALS"}, 2330 + #endif 2331 + #if defined(VIDIOC_G_ENC_INDEX) 2332 + {VIDIOC_G_ENC_INDEX, "VIDIOC_G_ENC_INDEX"}, 2333 + #endif 2334 + #if defined(VIDIOC_ENCODER_CMD) 2335 + {VIDIOC_ENCODER_CMD, "VIDIOC_ENCODER_CMD"}, 2336 + #endif 2337 + #if defined(VIDIOC_TRY_ENCODER_CMD) 2338 + {VIDIOC_TRY_ENCODER_CMD, "VIDIOC_TRY_ENCODER_CMD"}, 2339 + #endif 2340 + #if defined(VIDIOC_G_CHIP_IDENT) 2341 + {VIDIOC_G_CHIP_IDENT, "VIDIOC_G_CHIP_IDENT"}, 2342 + #endif 2343 + 2344 + #if defined(VIDIOC_OVERLAY_OLD) 2345 + {VIDIOC_OVERLAY_OLD, "VIDIOC_OVERLAY_OLD"}, 2346 + #endif 2347 + #if defined(VIDIOC_S_PARM_OLD) 2348 + {VIDIOC_S_PARM_OLD, "VIDIOC_S_PARM_OLD"}, 2349 + #endif 2350 + #if defined(VIDIOC_S_CTRL_OLD) 2351 + {VIDIOC_S_CTRL_OLD, "VIDIOC_S_CTRL_OLD"}, 2352 + #endif 2353 + #if defined(VIDIOC_G_AUDIO_OLD) 2354 + {VIDIOC_G_AUDIO_OLD, "VIDIOC_G_AUDIO_OLD"}, 2355 + #endif 2356 + #if defined(VIDIOC_G_AUDOUT_OLD) 2357 + {VIDIOC_G_AUDOUT_OLD, "VIDIOC_G_AUDOUT_OLD"}, 2358 + #endif 2359 + #if defined(VIDIOC_CROPCAP_OLD) 2360 + {VIDIOC_CROPCAP_OLD, "VIDIOC_CROPCAP_OLD"}, 2361 + #endif 2362 + {0xFFFFFFFF, ""} 2363 + }; 2364 + 2365 + static struct mess mess1[] = \ 2366 + { 2367 + #if defined(VIDIOCGCAP) 2368 + {VIDIOCGCAP, "VIDIOCGCAP"}, 2369 + #endif 2370 + #if defined(VIDIOCGCHAN) 2371 + {VIDIOCGCHAN, "VIDIOCGCHAN"}, 2372 + #endif 2373 + #if defined(VIDIOCSCHAN) 2374 + {VIDIOCSCHAN, "VIDIOCSCHAN"}, 2375 + #endif 2376 + #if defined(VIDIOCGTUNER) 2377 + {VIDIOCGTUNER, "VIDIOCGTUNER"}, 2378 + #endif 2379 + #if defined(VIDIOCSTUNER) 2380 + {VIDIOCSTUNER, "VIDIOCSTUNER"}, 2381 + #endif 2382 + #if defined(VIDIOCGPICT) 2383 + {VIDIOCGPICT, "VIDIOCGPICT"}, 2384 + #endif 2385 + #if defined(VIDIOCSPICT) 2386 + {VIDIOCSPICT, "VIDIOCSPICT"}, 2387 + #endif 2388 + #if defined(VIDIOCCAPTURE) 2389 + {VIDIOCCAPTURE, "VIDIOCCAPTURE"}, 2390 + #endif 2391 + #if defined(VIDIOCGWIN) 2392 + {VIDIOCGWIN, "VIDIOCGWIN"}, 2393 + #endif 2394 + #if defined(VIDIOCSWIN) 2395 + {VIDIOCSWIN, "VIDIOCSWIN"}, 2396 + #endif 2397 + #if defined(VIDIOCGFBUF) 2398 + {VIDIOCGFBUF, "VIDIOCGFBUF"}, 2399 + #endif 2400 + #if defined(VIDIOCSFBUF) 2401 + {VIDIOCSFBUF, "VIDIOCSFBUF"}, 2402 + #endif 2403 + #if defined(VIDIOCKEY) 2404 + {VIDIOCKEY, "VIDIOCKEY"}, 2405 + #endif 2406 + #if defined(VIDIOCGFREQ) 2407 + {VIDIOCGFREQ, "VIDIOCGFREQ"}, 2408 + #endif 2409 + #if defined(VIDIOCSFREQ) 2410 + {VIDIOCSFREQ, "VIDIOCSFREQ"}, 2411 + #endif 2412 + #if defined(VIDIOCGAUDIO) 2413 + {VIDIOCGAUDIO, "VIDIOCGAUDIO"}, 2414 + #endif 2415 + #if defined(VIDIOCSAUDIO) 2416 + {VIDIOCSAUDIO, "VIDIOCSAUDIO"}, 2417 + #endif 2418 + #if defined(VIDIOCSYNC) 2419 + {VIDIOCSYNC, "VIDIOCSYNC"}, 2420 + #endif 2421 + #if defined(VIDIOCMCAPTURE) 2422 + {VIDIOCMCAPTURE, "VIDIOCMCAPTURE"}, 2423 + #endif 2424 + #if defined(VIDIOCGMBUF) 2425 + {VIDIOCGMBUF, "VIDIOCGMBUF"}, 2426 + #endif 2427 + #if defined(VIDIOCGUNIT) 2428 + {VIDIOCGUNIT, "VIDIOCGUNIT"}, 2429 + #endif 2430 + #if defined(VIDIOCGCAPTURE) 2431 + {VIDIOCGCAPTURE, "VIDIOCGCAPTURE"}, 2432 + #endif 2433 + #if defined(VIDIOCSCAPTURE) 2434 + {VIDIOCSCAPTURE, "VIDIOCSCAPTURE"}, 2435 + #endif 2436 + #if defined(VIDIOCSPLAYMODE) 2437 + {VIDIOCSPLAYMODE, "VIDIOCSPLAYMODE"}, 2438 + #endif 2439 + #if defined(VIDIOCSWRITEMODE) 2440 + {VIDIOCSWRITEMODE, "VIDIOCSWRITEMODE"}, 2441 + #endif 2442 + #if defined(VIDIOCGPLAYINFO) 2443 + {VIDIOCGPLAYINFO, "VIDIOCGPLAYINFO"}, 2444 + #endif 2445 + #if defined(VIDIOCSMICROCODE) 2446 + {VIDIOCSMICROCODE, "VIDIOCSMICROCODE"}, 2447 + #endif 2448 + {0xFFFFFFFF, ""} 2449 + }; 2450 + 2451 + k = 0; 2452 + while (mess[k].name[0]) { 2453 + if (wot == mess[k].command) { 2454 + JOT(8, "ioctl 0x%08X is %s\n", \ 2455 + mess[k].command, &mess[k].name[0]); 2456 + return 0; 2457 + } 2458 + k++; 2459 + } 2460 + JOT(8, "ioctl 0x%08X is not in videodev2.h\n", wot); 2461 + 2462 + k = 0; 2463 + while (mess1[k].name[0]) { 2464 + if (wot == mess1[k].command) { 2465 + JOT(8, "ioctl 0x%08X is %s (V4L1)\n", \ 2466 + mess1[k].command, &mess1[k].name[0]); 2467 + return 0; 2468 + } 2469 + k++; 2470 + } 2471 + JOT(8, "ioctl 0x%08X is not in videodev.h\n", wot); 2472 + return -1; 2473 + } 2474 + /*****************************************************************************/ 2475 + int explain_cid(__u32 wot) 2476 + { 2477 + int k; 2478 + /*---------------------------------------------------------------------------*/ 2479 + /* 2480 + * THE DATA FOR THE ARRAY mess BELOW WERE CONSTRUCTED BY RUNNING THE FOLLOWING 2481 + * SHELL SCRIPT: 2482 + * # 2483 + * cat /usr/src/linux-headers-`uname -r`/include/linux/videodev2.h | \ 2484 + * grep "^#define V4L2_CID_" | \ 2485 + * sed -e "s,(.*$,,;p" | sed -e "N;s,\n,, " | \ 2486 + * sed -e "s/^#define / {/;s/#define /, \"/;s/$/\"},/" | \ 2487 + * sed -e "s, ,,g;s, ,,g" | grep -v "_BASE" | grep -v "MPEG" >cid.tmp 2488 + * echo "{0xFFFFFFFF,\"\"}" >>cid.tmp 2489 + * exit 0 2490 + * # 2491 + */ 2492 + /*---------------------------------------------------------------------------*/ 2493 + static struct mess 2494 + { 2495 + __u32 command; 2496 + char name[64]; 2497 + } mess[] = { 2498 + #if defined(V4L2_CID_USER_CLASS) 2499 + {V4L2_CID_USER_CLASS, "V4L2_CID_USER_CLASS"}, 2500 + #endif 2501 + #if defined(V4L2_CID_BRIGHTNESS) 2502 + {V4L2_CID_BRIGHTNESS, "V4L2_CID_BRIGHTNESS"}, 2503 + #endif 2504 + #if defined(V4L2_CID_CONTRAST) 2505 + {V4L2_CID_CONTRAST, "V4L2_CID_CONTRAST"}, 2506 + #endif 2507 + #if defined(V4L2_CID_SATURATION) 2508 + {V4L2_CID_SATURATION, "V4L2_CID_SATURATION"}, 2509 + #endif 2510 + #if defined(V4L2_CID_HUE) 2511 + {V4L2_CID_HUE, "V4L2_CID_HUE"}, 2512 + #endif 2513 + #if defined(V4L2_CID_AUDIO_VOLUME) 2514 + {V4L2_CID_AUDIO_VOLUME, "V4L2_CID_AUDIO_VOLUME"}, 2515 + #endif 2516 + #if defined(V4L2_CID_AUDIO_BALANCE) 2517 + {V4L2_CID_AUDIO_BALANCE, "V4L2_CID_AUDIO_BALANCE"}, 2518 + #endif 2519 + #if defined(V4L2_CID_AUDIO_BASS) 2520 + {V4L2_CID_AUDIO_BASS, "V4L2_CID_AUDIO_BASS"}, 2521 + #endif 2522 + #if defined(V4L2_CID_AUDIO_TREBLE) 2523 + {V4L2_CID_AUDIO_TREBLE, "V4L2_CID_AUDIO_TREBLE"}, 2524 + #endif 2525 + #if defined(V4L2_CID_AUDIO_MUTE) 2526 + {V4L2_CID_AUDIO_MUTE, "V4L2_CID_AUDIO_MUTE"}, 2527 + #endif 2528 + #if defined(V4L2_CID_AUDIO_LOUDNESS) 2529 + {V4L2_CID_AUDIO_LOUDNESS, "V4L2_CID_AUDIO_LOUDNESS"}, 2530 + #endif 2531 + #if defined(V4L2_CID_BLACK_LEVEL) 2532 + {V4L2_CID_BLACK_LEVEL, "V4L2_CID_BLACK_LEVEL"}, 2533 + #endif 2534 + #if defined(V4L2_CID_AUTO_WHITE_BALANCE) 2535 + {V4L2_CID_AUTO_WHITE_BALANCE, "V4L2_CID_AUTO_WHITE_BALANCE"}, 2536 + #endif 2537 + #if defined(V4L2_CID_DO_WHITE_BALANCE) 2538 + {V4L2_CID_DO_WHITE_BALANCE, "V4L2_CID_DO_WHITE_BALANCE"}, 2539 + #endif 2540 + #if defined(V4L2_CID_RED_BALANCE) 2541 + {V4L2_CID_RED_BALANCE, "V4L2_CID_RED_BALANCE"}, 2542 + #endif 2543 + #if defined(V4L2_CID_BLUE_BALANCE) 2544 + {V4L2_CID_BLUE_BALANCE, "V4L2_CID_BLUE_BALANCE"}, 2545 + #endif 2546 + #if defined(V4L2_CID_GAMMA) 2547 + {V4L2_CID_GAMMA, "V4L2_CID_GAMMA"}, 2548 + #endif 2549 + #if defined(V4L2_CID_WHITENESS) 2550 + {V4L2_CID_WHITENESS, "V4L2_CID_WHITENESS"}, 2551 + #endif 2552 + #if defined(V4L2_CID_EXPOSURE) 2553 + {V4L2_CID_EXPOSURE, "V4L2_CID_EXPOSURE"}, 2554 + #endif 2555 + #if defined(V4L2_CID_AUTOGAIN) 2556 + {V4L2_CID_AUTOGAIN, "V4L2_CID_AUTOGAIN"}, 2557 + #endif 2558 + #if defined(V4L2_CID_GAIN) 2559 + {V4L2_CID_GAIN, "V4L2_CID_GAIN"}, 2560 + #endif 2561 + #if defined(V4L2_CID_HFLIP) 2562 + {V4L2_CID_HFLIP, "V4L2_CID_HFLIP"}, 2563 + #endif 2564 + #if defined(V4L2_CID_VFLIP) 2565 + {V4L2_CID_VFLIP, "V4L2_CID_VFLIP"}, 2566 + #endif 2567 + #if defined(V4L2_CID_HCENTER) 2568 + {V4L2_CID_HCENTER, "V4L2_CID_HCENTER"}, 2569 + #endif 2570 + #if defined(V4L2_CID_VCENTER) 2571 + {V4L2_CID_VCENTER, "V4L2_CID_VCENTER"}, 2572 + #endif 2573 + #if defined(V4L2_CID_POWER_LINE_FREQUENCY) 2574 + {V4L2_CID_POWER_LINE_FREQUENCY, "V4L2_CID_POWER_LINE_FREQUENCY"}, 2575 + #endif 2576 + #if defined(V4L2_CID_HUE_AUTO) 2577 + {V4L2_CID_HUE_AUTO, "V4L2_CID_HUE_AUTO"}, 2578 + #endif 2579 + #if defined(V4L2_CID_WHITE_BALANCE_TEMPERATURE) 2580 + {V4L2_CID_WHITE_BALANCE_TEMPERATURE, "V4L2_CID_WHITE_BALANCE_TEMPERATURE"}, 2581 + #endif 2582 + #if defined(V4L2_CID_SHARPNESS) 2583 + {V4L2_CID_SHARPNESS, "V4L2_CID_SHARPNESS"}, 2584 + #endif 2585 + #if defined(V4L2_CID_BACKLIGHT_COMPENSATION) 2586 + {V4L2_CID_BACKLIGHT_COMPENSATION, "V4L2_CID_BACKLIGHT_COMPENSATION"}, 2587 + #endif 2588 + #if defined(V4L2_CID_CHROMA_AGC) 2589 + {V4L2_CID_CHROMA_AGC, "V4L2_CID_CHROMA_AGC"}, 2590 + #endif 2591 + #if defined(V4L2_CID_COLOR_KILLER) 2592 + {V4L2_CID_COLOR_KILLER, "V4L2_CID_COLOR_KILLER"}, 2593 + #endif 2594 + #if defined(V4L2_CID_LASTP1) 2595 + {V4L2_CID_LASTP1, "V4L2_CID_LASTP1"}, 2596 + #endif 2597 + #if defined(V4L2_CID_CAMERA_CLASS) 2598 + {V4L2_CID_CAMERA_CLASS, "V4L2_CID_CAMERA_CLASS"}, 2599 + #endif 2600 + #if defined(V4L2_CID_EXPOSURE_AUTO) 2601 + {V4L2_CID_EXPOSURE_AUTO, "V4L2_CID_EXPOSURE_AUTO"}, 2602 + #endif 2603 + #if defined(V4L2_CID_EXPOSURE_ABSOLUTE) 2604 + {V4L2_CID_EXPOSURE_ABSOLUTE, "V4L2_CID_EXPOSURE_ABSOLUTE"}, 2605 + #endif 2606 + #if defined(V4L2_CID_EXPOSURE_AUTO_PRIORITY) 2607 + {V4L2_CID_EXPOSURE_AUTO_PRIORITY, "V4L2_CID_EXPOSURE_AUTO_PRIORITY"}, 2608 + #endif 2609 + #if defined(V4L2_CID_PAN_RELATIVE) 2610 + {V4L2_CID_PAN_RELATIVE, "V4L2_CID_PAN_RELATIVE"}, 2611 + #endif 2612 + #if defined(V4L2_CID_TILT_RELATIVE) 2613 + {V4L2_CID_TILT_RELATIVE, "V4L2_CID_TILT_RELATIVE"}, 2614 + #endif 2615 + #if defined(V4L2_CID_PAN_RESET) 2616 + {V4L2_CID_PAN_RESET, "V4L2_CID_PAN_RESET"}, 2617 + #endif 2618 + #if defined(V4L2_CID_TILT_RESET) 2619 + {V4L2_CID_TILT_RESET, "V4L2_CID_TILT_RESET"}, 2620 + #endif 2621 + #if defined(V4L2_CID_PAN_ABSOLUTE) 2622 + {V4L2_CID_PAN_ABSOLUTE, "V4L2_CID_PAN_ABSOLUTE"}, 2623 + #endif 2624 + #if defined(V4L2_CID_TILT_ABSOLUTE) 2625 + {V4L2_CID_TILT_ABSOLUTE, "V4L2_CID_TILT_ABSOLUTE"}, 2626 + #endif 2627 + #if defined(V4L2_CID_FOCUS_ABSOLUTE) 2628 + {V4L2_CID_FOCUS_ABSOLUTE, "V4L2_CID_FOCUS_ABSOLUTE"}, 2629 + #endif 2630 + #if defined(V4L2_CID_FOCUS_RELATIVE) 2631 + {V4L2_CID_FOCUS_RELATIVE, "V4L2_CID_FOCUS_RELATIVE"}, 2632 + #endif 2633 + #if defined(V4L2_CID_FOCUS_AUTO) 2634 + {V4L2_CID_FOCUS_AUTO, "V4L2_CID_FOCUS_AUTO"}, 2635 + #endif 2636 + {0xFFFFFFFF, ""} 2637 + }; 2638 + 2639 + k = 0; 2640 + while (mess[k].name[0]) { 2641 + if (wot == mess[k].command) { 2642 + JOT(8, "ioctl 0x%08X is %s\n", \ 2643 + mess[k].command, &mess[k].name[0]); 2644 + return 0; 2645 + } 2646 + k++; 2647 + } 2648 + JOT(8, "cid 0x%08X is not in videodev2.h\n", wot); 2649 + return -1; 2650 + } 2651 + /*****************************************************************************/
+29
drivers/staging/easycap/easycap_ioctl.h
··· 1 + /***************************************************************************** 2 + * * 3 + * easycap_ioctl.h * 4 + * * 5 + *****************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + extern struct easycap_format easycap_format[]; 28 + extern struct v4l2_queryctrl easycap_control[]; 29 + extern unsigned int audio_bytes_per_fragment;
+1057
drivers/staging/easycap/easycap_low.c
··· 1 + /***************************************************************************** 2 + * * 3 + * * 4 + * easycap_low.c * 5 + * * 6 + * * 7 + *****************************************************************************/ 8 + /* 9 + * 10 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 11 + * 12 + * 13 + * This is free software; you can redistribute it and/or modify 14 + * it under the terms of the GNU General Public License as published by 15 + * the Free Software Foundation; either version 2 of the License, or 16 + * (at your option) any later version. 17 + * 18 + * The software is distributed in the hope that it will be useful, 19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 + * GNU General Public License for more details. 22 + * 23 + * You should have received a copy of the GNU General Public License 24 + * along with this software; if not, write to the Free Software 25 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 + * 27 + */ 28 + /*****************************************************************************/ 29 + /* 30 + * ACKNOWLEGEMENTS AND REFERENCES 31 + * ------------------------------ 32 + * This driver makes use of register information contained in the Syntek 33 + * Semicon DC-1125 driver hosted at 34 + * http://sourceforge.net/projects/syntekdriver/. 35 + * Particularly useful has been a patch to the latter driver provided by 36 + * Ivor Hewitt in January 2009. The NTSC implementation is taken from the 37 + * work of Ben Trask. 38 + */ 39 + /****************************************************************************/ 40 + 41 + #include "easycap_debug.h" 42 + #include "easycap.h" 43 + 44 + /*--------------------------------------------------------------------------*/ 45 + const struct stk1160config { int reg; int set; } stk1160config[256] = { 46 + {0x000, 0x0098}, 47 + {0x002, 0x0093}, 48 + 49 + {0x001, 0x0003}, 50 + {0x003, 0x0080}, 51 + {0x00D, 0x0000}, 52 + {0x00F, 0x0002}, 53 + {0x018, 0x0010}, 54 + {0x019, 0x0000}, 55 + {0x01A, 0x0014}, 56 + {0x01B, 0x000E}, 57 + {0x01C, 0x0046}, 58 + 59 + {0x100, 0x0033}, 60 + {0x103, 0x0000}, 61 + {0x104, 0x0000}, 62 + {0x105, 0x0000}, 63 + {0x106, 0x0000}, 64 + 65 + #if defined(PREFER_NTSC) 66 + 67 + #undef OLDMARGIN 68 + #if defined(OLDMARGIN) 69 + {0x110, 0x0008}, 70 + #else 71 + {0x110, 0x0014}, 72 + #endif /*OLDMARGIN*/ 73 + 74 + {0x111, 0x0000}, 75 + {0x112, 0x0003}, 76 + {0x113, 0x0000}, 77 + 78 + #if defined(OLDMARGIN) 79 + {0x114, 0x0508}, 80 + #else 81 + {0x114, 0x0514}, 82 + #endif /*OLDMARGIN*/ 83 + 84 + {0x115, 0x0005}, 85 + {0x116, 0x00F3}, 86 + {0x117, 0x0000}, 87 + 88 + #else /* ! PREFER_NTSC*/ 89 + 90 + #if defined(OLDMARGIN) 91 + {0x110, 0x0008}, 92 + #else 93 + {0x110, 0x0014}, 94 + #endif /*OLDMARGIN*/ 95 + 96 + {0x111, 0x0000}, 97 + {0x112, 0x0020}, 98 + {0x113, 0x0000}, 99 + 100 + #if defined(OLDMARGIN) 101 + {0x114, 0x0508}, 102 + #else 103 + {0x114, 0x0514}, 104 + #endif /*OLDMARGIN*/ 105 + 106 + {0x115, 0x0005}, 107 + {0x116, 0x0110}, 108 + {0x117, 0x0001}, 109 + 110 + #endif /* ! PREFER_NTSC*/ 111 + 112 + {0x202, 0x000F}, 113 + {0x203, 0x004A}, 114 + {0x2FF, 0x0000}, 115 + /*---------------------------------------------------------------------------*/ 116 + {0xFFF, 0xFFFF} 117 + }; 118 + /*--------------------------------------------------------------------------*/ 119 + const struct saa7113config { int reg; int set; } saa7113config[256] = { 120 + {0x01, 0x08}, 121 + {0x02, 0x80}, 122 + {0x03, 0x33}, 123 + {0x04, 0x00}, 124 + {0x05, 0x00}, 125 + {0x06, 0xE9}, 126 + {0x07, 0x0D}, 127 + #if defined(PREFER_NTSC) 128 + {0x08, 0x78}, 129 + #else 130 + {0x08, 0x38}, 131 + #endif /* ! PREFER_NTSC*/ 132 + {0x09, 0x00}, 133 + {0x0A, SAA_0A_DEFAULT}, 134 + {0x0B, SAA_0B_DEFAULT}, 135 + {0x0C, SAA_0C_DEFAULT}, 136 + {0x0D, SAA_0D_DEFAULT}, 137 + {0x0E, 0x01}, 138 + {0x0F, 0x36}, 139 + {0x10, 0x00}, 140 + {0x11, 0x0C}, 141 + {0x12, 0xE7}, 142 + {0x13, 0x00}, 143 + {0x15, 0x00}, 144 + {0x16, 0x00}, 145 + #if defined(PREFER_NTSC) 146 + {0x40, 0x82}, 147 + #else 148 + {0x40, 0x02}, 149 + #endif /* ! PREFER_NTSC*/ 150 + {0x41, 0xFF}, 151 + {0x42, 0xFF}, 152 + {0x43, 0xFF}, 153 + {0x44, 0xFF}, 154 + {0x45, 0xFF}, 155 + {0x46, 0xFF}, 156 + {0x47, 0xFF}, 157 + {0x48, 0xFF}, 158 + {0x49, 0xFF}, 159 + {0x4A, 0xFF}, 160 + {0x4B, 0xFF}, 161 + {0x4C, 0xFF}, 162 + {0x4D, 0xFF}, 163 + {0x4E, 0xFF}, 164 + {0x4F, 0xFF}, 165 + {0x50, 0xFF}, 166 + {0x51, 0xFF}, 167 + {0x52, 0xFF}, 168 + {0x53, 0xFF}, 169 + {0x54, 0xFF}, 170 + {0x55, 0xFF}, 171 + {0x56, 0xFF}, 172 + {0x57, 0xFF}, 173 + {0x58, 0x40}, 174 + {0x59, 0x54}, 175 + #if defined(PREFER_NTSC) 176 + {0x5A, 0x0A}, 177 + #else 178 + {0x5A, 0x07}, 179 + #endif /* ! PREFER_NTSC*/ 180 + {0x5B, 0x83}, 181 + {0xFF, 0xFF} 182 + }; 183 + /*--------------------------------------------------------------------------*/ 184 + 185 + /****************************************************************************/ 186 + int 187 + confirm_resolution(struct usb_device *p) 188 + { 189 + __u8 get0, get1, get2, get3, get4, get5, get6, get7; 190 + GET(p, 0x0110, &get0); 191 + GET(p, 0x0111, &get1); 192 + GET(p, 0x0112, &get2); 193 + GET(p, 0x0113, &get3); 194 + GET(p, 0x0114, &get4); 195 + GET(p, 0x0115, &get5); 196 + GET(p, 0x0116, &get6); 197 + GET(p, 0x0117, &get7); 198 + JOT(8, "0x%03X, 0x%03X, " \ 199 + "0x%03X, 0x%03X, " \ 200 + "0x%03X, 0x%03X, " \ 201 + "0x%03X, 0x%03X\n", \ 202 + get0, get1, get2, get3, get4, get5, get6, get7); 203 + JOT(8, "....cf PAL_720x526: " \ 204 + "0x%03X, 0x%03X, " \ 205 + "0x%03X, 0x%03X, " \ 206 + "0x%03X, 0x%03X, " \ 207 + "0x%03X, 0x%03X\n", \ 208 + 0x000, 0x000, 0x001, 0x000, 0x5A0, 0x005, 0x121, 0x001); 209 + JOT(8, "....cf PAL_704x526: " \ 210 + "0x%03X, 0x%03X, " \ 211 + "0x%03X, 0x%03X, " \ 212 + "0x%03X, 0x%03X, " \ 213 + "0x%03X, 0x%03X\n", \ 214 + 0x004, 0x000, 0x001, 0x000, 0x584, 0x005, 0x121, 0x001); 215 + JOT(8, "....cf VGA_640x480: " \ 216 + "0x%03X, 0x%03X, " \ 217 + "0x%03X, 0x%03X, " \ 218 + "0x%03X, 0x%03X, " \ 219 + "0x%03X, 0x%03X\n", \ 220 + 0x008, 0x000, 0x020, 0x000, 0x508, 0x005, 0x110, 0x001); 221 + return 0; 222 + } 223 + /****************************************************************************/ 224 + int 225 + confirm_stream(struct usb_device *p) 226 + { 227 + __u16 get2; 228 + __u8 igot; 229 + 230 + GET(p, 0x0100, &igot); get2 = 0x80 & igot; 231 + if (0x80 == get2) 232 + JOT(8, "confirm_stream: OK\n"); 233 + else 234 + JOT(8, "confirm_stream: STUCK\n"); 235 + return 0; 236 + } 237 + /****************************************************************************/ 238 + int 239 + setup_stk(struct usb_device *p) 240 + { 241 + int i0; 242 + 243 + i0 = 0; 244 + while (0xFFF != stk1160config[i0].reg) { 245 + SET(p, stk1160config[i0].reg, stk1160config[i0].set); 246 + i0++; 247 + } 248 + 249 + write_300(p); 250 + 251 + return 0; 252 + } 253 + /****************************************************************************/ 254 + int 255 + setup_saa(struct usb_device *p) 256 + { 257 + int i0, ir; 258 + 259 + 260 + set2to78(p); 261 + 262 + 263 + i0 = 0; 264 + while (0xFF != saa7113config[i0].reg) { 265 + ir = write_saa(p, saa7113config[i0].reg, saa7113config[i0].set); 266 + i0++; 267 + } 268 + return 0; 269 + } 270 + /****************************************************************************/ 271 + int 272 + write_000(struct usb_device *p, __u16 set2, __u16 set0) 273 + { 274 + __u8 igot0, igot2; 275 + 276 + GET(p, 0x0002, &igot2); 277 + GET(p, 0x0000, &igot0); 278 + SET(p, 0x0002, set2); 279 + SET(p, 0x0000, set0); 280 + return 0; 281 + } 282 + /****************************************************************************/ 283 + int 284 + write_saa(struct usb_device *p, __u16 reg0, __u16 set0) 285 + { 286 + SET(p, 0x200, 0x00); 287 + SET(p, 0x204, reg0); 288 + SET(p, 0x205, set0); 289 + SET(p, 0x200, 0x01); 290 + return wait_i2c(p); 291 + } 292 + /****************************************************************************/ 293 + /*--------------------------------------------------------------------------*/ 294 + /* 295 + * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) 296 + * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A 297 + * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO SET 298 + * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO SET 299 + * REGISTER 504: TARGET ADDRESS ON VT1612A 300 + */ 301 + /*--------------------------------------------------------------------------*/ 302 + int 303 + write_vt(struct usb_device *p, __u16 reg0, __u16 set0) 304 + { 305 + __u8 igot; 306 + __u16 got502, got503; 307 + __u16 set502, set503; 308 + 309 + SET(p, 0x0504, reg0); 310 + SET(p, 0x0500, 0x008B); 311 + 312 + GET(p, 0x0502, &igot); got502 = (0xFF & igot); 313 + GET(p, 0x0503, &igot); got503 = (0xFF & igot); 314 + 315 + JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n", \ 316 + reg0, set0, ((got503 << 8) | got502)); 317 + 318 + set502 = (0x00FF & set0); 319 + set503 = ((0xFF00 & set0) >> 8); 320 + 321 + SET(p, 0x0504, reg0); 322 + SET(p, 0x0502, set502); 323 + SET(p, 0x0503, set503); 324 + SET(p, 0x0500, 0x008C); 325 + 326 + return 0; 327 + } 328 + /****************************************************************************/ 329 + /*--------------------------------------------------------------------------*/ 330 + /* 331 + * REGISTER 500: SETTING VALUE TO 0x008B READS FROM VT1612A (?) 332 + * REGISTER 500: SETTING VALUE TO 0x008C WRITES TO VT1612A 333 + * REGISTER 502: LEAST SIGNIFICANT BYTE OF VALUE TO GET 334 + * REGISTER 503: MOST SIGNIFICANT BYTE OF VALUE TO GET 335 + * REGISTER 504: TARGET ADDRESS ON VT1612A 336 + */ 337 + /*--------------------------------------------------------------------------*/ 338 + int 339 + read_vt(struct usb_device *p, __u16 reg0) 340 + { 341 + __u8 igot; 342 + __u16 got502, got503; 343 + 344 + SET(p, 0x0504, reg0); 345 + SET(p, 0x0500, 0x008B); 346 + 347 + GET(p, 0x0502, &igot); got502 = (0xFF & igot); 348 + GET(p, 0x0503, &igot); got503 = (0xFF & igot); 349 + 350 + JOT(16, "read_vt(., 0x%04X): has 0x%04X\n", reg0, ((got503 << 8) | got502)); 351 + 352 + return (got503 << 8) | got502; 353 + } 354 + /****************************************************************************/ 355 + /*--------------------------------------------------------------------------*/ 356 + /* 357 + * THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO. 358 + */ 359 + /*--------------------------------------------------------------------------*/ 360 + int 361 + write_300(struct usb_device *p) 362 + { 363 + SET(p, 0x300, 0x0012); 364 + SET(p, 0x350, 0x002D); 365 + SET(p, 0x351, 0x0001); 366 + SET(p, 0x352, 0x0000); 367 + SET(p, 0x353, 0x0000); 368 + SET(p, 0x300, 0x0080); 369 + return 0; 370 + } 371 + /****************************************************************************/ 372 + /*--------------------------------------------------------------------------*/ 373 + /* 374 + * NOTE: THE FOLLOWING IS NOT CHECKED: 375 + * REGISTER 0x0F, WHICH IS INVOLVED IN CHROMINANCE AUTOMATIC GAIN CONTROL. 376 + */ 377 + /*--------------------------------------------------------------------------*/ 378 + int 379 + check_saa(struct usb_device *p) 380 + { 381 + int i0, ir, rc; 382 + i0 = 0; 383 + 384 + rc = 0; 385 + while (0xFF != saa7113config[i0].reg) { 386 + if (0x0F == saa7113config[i0].reg) { 387 + i0++; continue; 388 + } 389 + 390 + ir = read_saa(p, saa7113config[i0].reg); 391 + if (ir != saa7113config[i0].set) { 392 + SAY("SAA register 0x%02X has 0x%02X, expected 0x%02X\n", \ 393 + saa7113config[i0].reg, ir, saa7113config[i0].set); 394 + rc--; 395 + } 396 + i0++; 397 + } 398 + if (-8 > rc) 399 + return rc; 400 + else 401 + return 0; 402 + } 403 + /****************************************************************************/ 404 + int 405 + merit_saa(struct usb_device *p) 406 + { 407 + int rc; 408 + 409 + rc = read_saa(p, 0x1F); 410 + if ((0 > rc) || (0x02 & rc)) 411 + return 1 ; 412 + else 413 + return 0; 414 + } 415 + /****************************************************************************/ 416 + int 417 + ready_saa(struct usb_device *p) 418 + { 419 + int j, rc; 420 + static int max = 10; 421 + 422 + j = 0; 423 + while (max > j) { 424 + rc = read_saa(p, 0x1F); 425 + if (0 <= rc) { 426 + if ((1 == (0x01 & rc))&&(0 == (0x40 & rc))) 427 + break; 428 + } 429 + msleep(100); j++; 430 + } 431 + if (max == j) 432 + return -1; 433 + else { 434 + if (0x20 & rc) 435 + JOT(8, "hardware detects 60 Hz\n"); 436 + else 437 + JOT(8, "hardware detects 50 Hz\n"); 438 + if (0x80 & rc) 439 + JOT(8, "hardware detects interlacing\n"); 440 + else 441 + JOT(8, "hardware detects no interlacing\n"); 442 + } 443 + return 0; 444 + } 445 + /****************************************************************************/ 446 + /*--------------------------------------------------------------------------*/ 447 + /* 448 + * NOTE: THE FOLLOWING ARE NOT CHECKED: 449 + * REGISTERS 0x000, 0x002: FUNCTIONALITY IS NOT KNOWN 450 + * REGISTER 0x100: ACCEPT ALSO (0x80 | stk1160config[.].set) 451 + */ 452 + /*--------------------------------------------------------------------------*/ 453 + int 454 + check_stk(struct usb_device *p) 455 + { 456 + int i0, ir; 457 + i0 = 0; 458 + while (0xFFF != stk1160config[i0].reg) { 459 + if (0x000 == stk1160config[i0].reg) { 460 + i0++; continue; 461 + } 462 + if (0x002 == stk1160config[i0].reg) { 463 + i0++; continue; 464 + } 465 + 466 + ir = read_stk(p, stk1160config[i0].reg); 467 + 468 + if (0x100 == stk1160config[i0].reg) { 469 + if ((ir != (0xFF & stk1160config[i0].set)) && \ 470 + (ir != (0x80 | (0xFF & stk1160config[i0].set))) && \ 471 + (0xFFFF != stk1160config[i0].set)) { 472 + SAY("STK register 0x%03X has 0x%02X, " \ 473 + "expected 0x%02X\n", \ 474 + stk1160config[i0].reg, ir, \ 475 + stk1160config[i0].set); 476 + } 477 + i0++; continue; 478 + } 479 + 480 + if ((ir != (0xFF & stk1160config[i0].set)) && \ 481 + (0xFFFF != stk1160config[i0].set)) { 482 + SAY("STK register 0x%03X has 0x%02X, " \ 483 + "expected 0x%02X\n", \ 484 + stk1160config[i0].reg, ir, \ 485 + stk1160config[i0].set); 486 + } 487 + i0++; 488 + } 489 + return 0; 490 + } 491 + /****************************************************************************/ 492 + int 493 + read_saa(struct usb_device *p, __u16 reg0) 494 + { 495 + __u8 igot; 496 + 497 + SET(p, 0x208, reg0); 498 + SET(p, 0x200, 0x20); 499 + if (0 != wait_i2c(p)) 500 + return -1; 501 + igot = 0; 502 + GET(p, 0x0209, &igot); 503 + return igot; 504 + } 505 + /****************************************************************************/ 506 + int 507 + read_stk(struct usb_device *p, __u32 reg0) 508 + { 509 + __u8 igot; 510 + 511 + igot = 0; 512 + GET(p, reg0, &igot); 513 + return igot; 514 + } 515 + /*****************************************************************************/ 516 + /*---------------------------------------------------------------------------*/ 517 + /* 518 + * HARDWARE USERSPACE INPUT NUMBER PHYSICAL INPUT DRIVER input VALUE 519 + * 520 + * CVBS+S-VIDEO 0 or 1 CVBS 1 521 + * FOUR-CVBS 0 or 1 CVBS1 1 522 + * FOUR-CVBS 2 CVBS2 2 523 + * FOUR-CVBS 3 CVBS3 3 524 + * FOUR-CVBS 4 CVBS4 4 525 + * CVBS+S-VIDEO 5 S-VIDEO 5 526 + * 527 + * WHEN 5==input THE ARGUMENT mode MUST ALSO BE SUPPLIED: 528 + * 529 + * mode 7 => GAIN TO BE SET EXPLICITLY USING REGISTER 0x05 (UNTESTED) 530 + * mode 9 => USE AUTOMATIC GAIN CONTROL (DEFAULT) 531 + * 532 + */ 533 + /*---------------------------------------------------------------------------*/ 534 + int 535 + select_input(struct usb_device *p, int input, int mode) 536 + { 537 + 538 + stop_100(p); 539 + 540 + msleep(20); 541 + switch (input) { 542 + case 0: 543 + case 1: { 544 + SET(p, 0x0000, 0x0098); break; 545 + } 546 + case 2: { 547 + SET(p, 0x0000, 0x0090); break; 548 + } 549 + case 3: { 550 + SET(p, 0x0000, 0x0088); break; 551 + } 552 + case 4: { 553 + SET(p, 0x0000, 0x0080); break; 554 + } 555 + case 5: { 556 + if (9 != mode) 557 + mode = 7; 558 + switch (mode) { 559 + case 7: 560 + { 561 + if (0 != write_saa(p, 0x02, 0x87)) { 562 + SAY("ERROR: failed to set SAA " \ 563 + "register 0x02 for input " \ 564 + "%i\n", input); 565 + } 566 + if (0 != write_saa(p, 0x05, 0xFF)) { 567 + SAY("ERROR: failed to set SAA " \ 568 + "register 0x05 for input " \ 569 + "%i\n", input); 570 + } 571 + break; 572 + } 573 + case 9: 574 + { 575 + if (0 != write_saa(p, 0x02, 0x89)) { 576 + SAY("ERROR: failed to set SAA " \ 577 + "register 0x02 for input " \ 578 + "%i\n", input); 579 + } 580 + if (0 != write_saa(p, 0x05, 0x00)) { 581 + SAY("ERROR: failed to set SAA " \ 582 + "register 0x05 for input " \ 583 + "%i\n", input); 584 + } 585 + break; 586 + } 587 + default: 588 + { 589 + SAY("MISTAKE: bad mode: %i\n", mode); 590 + return -1; 591 + } 592 + } 593 + if (0 != write_saa(p, 0x04, 0x00)) { 594 + SAY("ERROR: failed to set SAA register 0x04 " \ 595 + "for input %i\n", input); 596 + } 597 + if (0 != write_saa(p, 0x09, 0x80)) { 598 + SAY("ERROR: failed to set SAA register 0x09 " \ 599 + "for input %i\n", input); 600 + } 601 + break; 602 + } 603 + default: 604 + { 605 + SAY("ERROR: bad input: %i\n", input); 606 + return -1; 607 + } 608 + } 609 + msleep(20); 610 + SET(p, 0x0002, 0x0093); 611 + msleep(20); 612 + 613 + start_100(p); 614 + 615 + return 0; 616 + } 617 + /****************************************************************************/ 618 + int 619 + set_resolution(struct usb_device *p, \ 620 + __u16 set0, __u16 set1, __u16 set2, __u16 set3) 621 + { 622 + __u16 u0x0111, u0x0113, u0x0115, u0x0117; 623 + 624 + u0x0111 = ((0xFF00 & set0) >> 8); 625 + u0x0113 = ((0xFF00 & set1) >> 8); 626 + u0x0115 = ((0xFF00 & set2) >> 8); 627 + u0x0117 = ((0xFF00 & set3) >> 8); 628 + 629 + SET(p, 0x0110, (0x00FF & set0)); 630 + SET(p, 0x0111, u0x0111); 631 + SET(p, 0x0112, (0x00FF & set1)); 632 + SET(p, 0x0113, u0x0113); 633 + SET(p, 0x0114, (0x00FF & set2)); 634 + SET(p, 0x0115, u0x0115); 635 + SET(p, 0x0116, (0x00FF & set3)); 636 + SET(p, 0x0117, u0x0117); 637 + 638 + return 0; 639 + } 640 + /****************************************************************************/ 641 + int 642 + start_100(struct usb_device *p) 643 + { 644 + __u16 get0; 645 + __u8 igot; 646 + 647 + GET(p, 0x0100, &igot); get0 = igot; 648 + msleep(0x1f4); 649 + SET(p, 0x0100, (0x80 | get0)); 650 + msleep(0x1f4); 651 + return 0; 652 + } 653 + /****************************************************************************/ 654 + int 655 + stop_100(struct usb_device *p) 656 + { 657 + __u16 get0; 658 + __u8 igot; 659 + 660 + GET(p, 0x0100, &igot); get0 = igot; 661 + msleep(0x1f4); 662 + SET(p, 0x0100, (0x7F & get0)); 663 + msleep(0x1f4); 664 + return 0; 665 + } 666 + /****************************************************************************/ 667 + /*--------------------------------------------------------------------------*/ 668 + /* 669 + * FUNCTION wait_i2c() RETURNS 0 ON SUCCESS 670 + */ 671 + /*--------------------------------------------------------------------------*/ 672 + int 673 + wait_i2c(struct usb_device *p) 674 + { 675 + __u16 get0; 676 + __u8 igot; 677 + const int max = 4; 678 + int k; 679 + 680 + for (k = 0; k < max; k++) { 681 + GET(p, 0x0201, &igot); get0 = igot; 682 + switch (get0) { 683 + case 0x04: 684 + case 0x01: { 685 + return 0; 686 + } 687 + case 0x00: { 688 + msleep(10); 689 + continue; 690 + } 691 + default: { 692 + return get0 - 1; 693 + } 694 + } 695 + } 696 + return -1; 697 + } 698 + /****************************************************************************/ 699 + int 700 + regset(struct usb_device *pusb_device, __u16 index, __u16 value) 701 + { 702 + __u16 igot; 703 + int rc0, rc1; 704 + 705 + if (!pusb_device) 706 + return -EFAULT; 707 + 708 + rc1 = 0; igot = 0; 709 + rc0 = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ 710 + (__u8)0x01, \ 711 + (__u8)(USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ 712 + (__u16)value, \ 713 + (__u16)index, \ 714 + (void *)NULL, \ 715 + (__u16)0, \ 716 + (int)500); 717 + 718 + #if defined(NOREADBACK) 719 + # 720 + #else 721 + rc1 = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \ 722 + (__u8)0x00, \ 723 + (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ 724 + (__u16)0x00, \ 725 + (__u16)index, \ 726 + (void *)&igot, \ 727 + (__u16)sizeof(__u16), \ 728 + (int)50000); 729 + igot = 0xFF & igot; 730 + switch (index) { 731 + case 0x000: 732 + case 0x500: 733 + case 0x502: 734 + case 0x503: 735 + case 0x504: 736 + case 0x506: 737 + case 0x507: { 738 + break; 739 + } 740 + case 0x204: 741 + case 0x205: 742 + case 0x350: 743 + case 0x351: { 744 + if (0 != igot) { 745 + JOT(8, "unexpected 0x%02X for STK register 0x%03X\n", \ 746 + igot, index); 747 + } 748 + break; 749 + } 750 + case 0x114: 751 + case 0x116: { 752 + if ((0xFF & value) != igot) { 753 + JOT(8, "unexpected 0x%02X != 0x%02X " \ 754 + "for STK register 0x%03X\n", \ 755 + igot, value, index); 756 + } 757 + break; 758 + } 759 + case 0x200: { 760 + if (0 == igot) 761 + break; 762 + } 763 + default: { 764 + if (value != igot) { 765 + JOT(8, "unexpected 0x%02X != 0x%02X " \ 766 + "for STK register 0x%03X\n", \ 767 + igot, value, index); 768 + } 769 + break; 770 + } 771 + } 772 + #endif /* ! NOREADBACK*/ 773 + 774 + return (0 > rc0) ? rc0 : rc1; 775 + } 776 + /*****************************************************************************/ 777 + int 778 + regget(struct usb_device *pusb_device, __u16 index, void *pvoid) 779 + { 780 + int ir; 781 + 782 + if (!pusb_device) 783 + return -EFAULT; 784 + 785 + ir = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0), \ 786 + (__u8)0x00, \ 787 + (__u8)(USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE), \ 788 + (__u16)0x00, \ 789 + (__u16)index, \ 790 + (void *)pvoid, \ 791 + sizeof(__u8), \ 792 + (int)50000); 793 + return 0xFF & ir; 794 + } 795 + /*****************************************************************************/ 796 + int 797 + wakeup_device(struct usb_device *pusb_device) 798 + { 799 + return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ 800 + (__u8)USB_REQ_SET_FEATURE, \ 801 + (__u8)(USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE), \ 802 + USB_DEVICE_REMOTE_WAKEUP, \ 803 + (__u16)0, \ 804 + (void *) NULL, \ 805 + (__u16)0, \ 806 + (int)50000); 807 + } 808 + /*****************************************************************************/ 809 + /*---------------------------------------------------------------------------*/ 810 + /* 811 + * IMPORTANT: 812 + * THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) 813 + * CAUSES MUTING IF THE VALUE 0x0100 IS SENT. 814 + * TO ENABLE AUDIO THE VALUE 0x0200 MUST BE SENT. 815 + */ 816 + /*---------------------------------------------------------------------------*/ 817 + int 818 + audio_setup(struct easycap *peasycap) 819 + { 820 + struct usb_device *pusb_device; 821 + static __u8 request = 0x01; 822 + static __u8 requesttype = \ 823 + (__u8)(USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE); 824 + 825 + static __u16 value_unmute = 0x0200; 826 + static __u16 index = 0x0301; 827 + 828 + static unsigned char buffer[1]; 829 + static __u16 length = 1; 830 + int rc; 831 + 832 + if (NULL == peasycap) 833 + return -EFAULT; 834 + 835 + pusb_device = peasycap->pusb_device; 836 + if (NULL == pusb_device) 837 + return -EFAULT; 838 + 839 + JOT(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n", \ 840 + requesttype, request, \ 841 + (0x00FF & value_unmute), \ 842 + (0xFF00 & value_unmute) >> 8, \ 843 + (0x00FF & index), \ 844 + (0xFF00 & index) >> 8, \ 845 + (0x00FF & length), \ 846 + (0xFF00 & length) >> 8); 847 + 848 + buffer[0] = 0x01; 849 + 850 + rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0), \ 851 + (__u8)request, \ 852 + (__u8)requesttype, \ 853 + (__u16)value_unmute, \ 854 + (__u16)index, \ 855 + (void *)&buffer[0], \ 856 + (__u16)length, \ 857 + (int)50000); 858 + 859 + JOT(8, "0x%02X=buffer\n", *((__u8 *) &buffer[0])); 860 + if (rc != (int)length) 861 + SAY("ERROR: usb_control_msg returned %i\n", rc); 862 + 863 + /*--------------------------------------------------------------------------*/ 864 + /* 865 + * REGISTER 500: SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ??? 866 + * REGISTER 506: ANALOGUE AUDIO ATTENTUATOR ??? 867 + * FOR THE CVBS+S-VIDEO HARDWARE: 868 + * SETTING VALUE TO 0x0000 GIVES QUIET SOUND. 869 + * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. 870 + * FOR THE FOUR-CVBS HARDWARE: 871 + * SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT. 872 + * REGISTER 507: ANALOGUE AUDIO PREAMPLIFIER ON/OFF ??? 873 + * FOR THE CVBS-S-VIDEO HARDWARE: 874 + * SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND. 875 + * THE UPPER BYTE SEEMS TO HAVE NO EFFECT. 876 + */ 877 + /*--------------------------------------------------------------------------*/ 878 + 879 + SET(pusb_device, 0x0500, 0x0094); 880 + 881 + SET(pusb_device, 0x0500, 0x008C); 882 + 883 + SET(pusb_device, 0x0506, 0x0001); 884 + SET(pusb_device, 0x0507, 0x0000); 885 + 886 + if (false == peasycap->microphone) { 887 + /*-------------------------------------------------------------------*/ 888 + /* 889 + * SELECT AUDIO SOURCE "LINE IN" AND SET DEFAULT GAIN TO 0dB. 890 + */ 891 + /*-------------------------------------------------------------------*/ 892 + write_vt(pusb_device, 0x0002, 0x8000); 893 + write_vt(pusb_device, 0x001C, 0x8000); 894 + 895 + write_vt(pusb_device, 0x000E, 0x0000); 896 + write_vt(pusb_device, 0x0010, 0x0000); 897 + write_vt(pusb_device, 0x0012, 0x8000); 898 + write_vt(pusb_device, 0x0016, 0x0000); 899 + 900 + write_vt(pusb_device, 0x001A, 0x0404); 901 + write_vt(pusb_device, 0x0002, 0x0000); 902 + write_vt(pusb_device, 0x001C, 0x0000); 903 + } else { 904 + /*-------------------------------------------------------------------*/ 905 + /* 906 + * SELECT AUDIO SOURCE "MIC" AND SET DEFAULT GAIN TO 0 dB. 907 + * 908 + * REGISTER 0x000E CAN BE SET TO PROVIDE UP TO 34.5 dB ATTENTUATION, 909 + * BUT THIS HAS NOT PROVED NECESSARY FOR THE FEW SIGNAL SOURCES 910 + * TESTED HITHERTO. 911 + */ 912 + /*-------------------------------------------------------------------*/ 913 + write_vt(pusb_device, 0x0006, 0x8000); 914 + write_vt(pusb_device, 0x001C, 0x8000); 915 + 916 + write_vt(pusb_device, 0x000E, 0x0008); 917 + 918 + write_vt(pusb_device, 0x0010, 0x0000); 919 + write_vt(pusb_device, 0x0012, 0x8000); 920 + write_vt(pusb_device, 0x0016, 0x0000); 921 + 922 + write_vt(pusb_device, 0x001A, 0x0000); 923 + write_vt(pusb_device, 0x0006, 0x0000); 924 + write_vt(pusb_device, 0x001C, 0x0000); 925 + } 926 + 927 + check_vt(pusb_device); 928 + 929 + return 0; 930 + } 931 + /*****************************************************************************/ 932 + int 933 + check_vt(struct usb_device *pusb_device) 934 + { 935 + int igot; 936 + 937 + igot = read_vt(pusb_device, 0x0002); 938 + if (0 > igot) 939 + SAY("ERROR: failed to read VT1612A register 0x02\n"); 940 + if (0x8000 & igot) 941 + SAY("register 0x%02X muted\n", 0x02); 942 + 943 + igot = read_vt(pusb_device, 0x000E); 944 + if (0 > igot) 945 + SAY("ERROR: failed to read VT1612A register 0x0E\n"); 946 + if (0x8000 & igot) 947 + SAY("register 0x%02X muted\n", 0x0E); 948 + 949 + igot = read_vt(pusb_device, 0x0010); 950 + if (0 > igot) 951 + SAY("ERROR: failed to read VT1612A register 0x10\n"); 952 + if (0x8000 & igot) 953 + SAY("register 0x%02X muted\n", 0x10); 954 + 955 + igot = read_vt(pusb_device, 0x0012); 956 + if (0 > igot) 957 + SAY("ERROR: failed to read VT1612A register 0x12\n"); 958 + if (0x8000 & igot) 959 + SAY("register 0x%02X muted\n", 0x12); 960 + 961 + igot = read_vt(pusb_device, 0x0016); 962 + if (0 > igot) 963 + SAY("ERROR: failed to read VT1612A register 0x16\n"); 964 + if (0x8000 & igot) 965 + SAY("register 0x%02X muted\n", 0x16); 966 + 967 + igot = read_vt(pusb_device, 0x001A); 968 + if (0 > igot) 969 + SAY("ERROR: failed to read VT1612A register 0x1A\n"); 970 + if (0x8000 & igot) 971 + SAY("register 0x%02X muted\n", 0x1A); 972 + 973 + igot = read_vt(pusb_device, 0x001C); 974 + if (0 > igot) 975 + SAY("ERROR: failed to read VT1612A register 0x1C\n"); 976 + if (0x8000 & igot) 977 + SAY("register 0x%02X muted\n", 0x1C); 978 + 979 + return 0; 980 + } 981 + /*****************************************************************************/ 982 + /*---------------------------------------------------------------------------*/ 983 + /* 984 + * NOTE: THIS DOES INCREASE THE VOLUME DRAMATICALLY: 985 + * audio_gainset(pusb_device, 0x000F); 986 + * 987 + * IF 16<loud<31 VT1621A REGISTER 0x1C IS SET FOR POSITIVE GAIN. 988 + * IF loud<=16 VT1621A REGISTER 0x1C IS SET FOR ZERO GAIN. 989 + * THERE IS NEVER ANY (ADDITIONAL) ATTENUATION. 990 + */ 991 + /*---------------------------------------------------------------------------*/ 992 + int 993 + audio_gainset(struct usb_device *pusb_device, __s8 loud) 994 + { 995 + int igot; 996 + __u8 u8; 997 + __u16 mute; 998 + 999 + if (16 > loud) 1000 + loud = 16; 1001 + u8 = 0x000F & (__u8)(loud - 16); 1002 + 1003 + write_vt(pusb_device, 0x0002, 0x8000); 1004 + 1005 + igot = read_vt(pusb_device, 0x001C); 1006 + if (0 > igot) { 1007 + SAY("ERROR: failed to read VT1612A register 0x1C\n"); 1008 + mute = 0x0000; 1009 + } else 1010 + mute = 0x8000 & ((unsigned int)igot); 1011 + 1012 + JOT(8, "0x%04X=(mute|u8|(u8<<8))\n", mute | u8 | (u8 << 8)); 1013 + 1014 + write_vt(pusb_device, 0x001C, 0x8000); 1015 + write_vt(pusb_device, 0x001C, (mute | u8 | (u8 << 8))); 1016 + write_vt(pusb_device, 0x0002, 0x0000); 1017 + 1018 + return 0; 1019 + } 1020 + /*****************************************************************************/ 1021 + int 1022 + audio_gainget(struct usb_device *pusb_device) 1023 + { 1024 + int igot; 1025 + 1026 + igot = read_vt(pusb_device, 0x001C); 1027 + if (0 > igot) 1028 + SAY("ERROR: failed to read VT1612A register 0x1C\n"); 1029 + return igot; 1030 + } 1031 + /*****************************************************************************/ 1032 + int 1033 + set2to78(struct usb_device *p) 1034 + { 1035 + int ir; 1036 + 1037 + msleep(20); 1038 + ir = regset(p, 0x0002, 0x0078); 1039 + if (0 > ir) 1040 + SAY("ERROR: failed to set register 0x0002 to 0x0078\n"); 1041 + msleep(20); 1042 + return ir; 1043 + } 1044 + /*****************************************************************************/ 1045 + int 1046 + set2to93(struct usb_device *p) 1047 + { 1048 + int ir; 1049 + 1050 + msleep(20); 1051 + ir = regset(p, 0x0002, 0x0093); 1052 + if (0 > ir) 1053 + SAY("ERROR: failed to set register 0x0002 to 0x0078\n"); 1054 + msleep(20); 1055 + return ir; 1056 + } 1057 + /*****************************************************************************/
+4342
drivers/staging/easycap/easycap_main.c
··· 1 + /****************************************************************************** 2 + * * 3 + * easycap_main.c * 4 + * * 5 + * Video driver for EasyCAP USB2.0 Video Capture Device DC60 * 6 + * * 7 + * * 8 + ******************************************************************************/ 9 + /* 10 + * 11 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 12 + * 13 + * 14 + * This is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * The software is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this software; if not, write to the Free Software 26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 + * 28 + */ 29 + /*****************************************************************************/ 30 + 31 + #include "easycap.h" 32 + #include "easycap_standard.h" 33 + 34 + int easycap_debug; 35 + module_param(easycap_debug, int, S_IRUGO | S_IWUSR); 36 + 37 + unsigned int audio_pages_per_fragment; 38 + unsigned int audio_bytes_per_fragment; 39 + unsigned int audio_buffer_page_many; 40 + 41 + /*---------------------------------------------------------------------------*/ 42 + /* 43 + * PARAMETERS APPLICABLE TO ENTIRE DRIVER, I.E. BOTH VIDEO AND AUDIO 44 + */ 45 + /*---------------------------------------------------------------------------*/ 46 + struct usb_device_id easycap_usb_device_id_table[] = { 47 + { USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID) }, 48 + { } 49 + }; 50 + MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table); 51 + struct usb_driver easycap_usb_driver = { 52 + .name = "easycap", 53 + .id_table = easycap_usb_device_id_table, 54 + .probe = easycap_usb_probe, 55 + .disconnect = easycap_usb_disconnect, 56 + }; 57 + /*---------------------------------------------------------------------------*/ 58 + /* 59 + * PARAMETERS USED WHEN REGISTERING THE VIDEO INTERFACE 60 + * 61 + * NOTE: SOME KERNELS IGNORE usb_class_driver.minor_base, AS MENTIONED BY 62 + * CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGE 253. 63 + * THIS IS THE CASE FOR OpenSUSE. 64 + */ 65 + /*---------------------------------------------------------------------------*/ 66 + const struct file_operations easycap_fops = { 67 + .owner = THIS_MODULE, 68 + .open = easycap_open, 69 + .release = easycap_release, 70 + .ioctl = easycap_ioctl, 71 + .poll = easycap_poll, 72 + .mmap = easycap_mmap, 73 + .llseek = no_llseek, 74 + }; 75 + struct vm_operations_struct easycap_vm_ops = { 76 + .open = easycap_vma_open, 77 + .close = easycap_vma_close, 78 + .fault = easycap_vma_fault, 79 + }; 80 + struct usb_class_driver easycap_class = { 81 + .name = "usb/easycap%d", 82 + .fops = &easycap_fops, 83 + .minor_base = USB_SKEL_MINOR_BASE, 84 + }; 85 + 86 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 87 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 88 + #if defined(EASYCAP_NEEDS_V4L2_FOPS) 89 + struct v4l2_file_operations v4l2_fops = { 90 + .owner = THIS_MODULE, 91 + .open = easycap_open_noinode, 92 + .release = easycap_release_noinode, 93 + .ioctl = easycap_ioctl_noinode, 94 + .poll = easycap_poll, 95 + .mmap = easycap_mmap, 96 + }; 97 + #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ 98 + int video_device_many /*=0*/; 99 + struct video_device *pvideo_array[VIDEO_DEVICE_MANY], *pvideo_device; 100 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 101 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 102 + 103 + /*--------------------------------------------------------------------------*/ 104 + /* 105 + * PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE 106 + */ 107 + /*--------------------------------------------------------------------------*/ 108 + const struct file_operations easysnd_fops = { 109 + .owner = THIS_MODULE, 110 + .open = easysnd_open, 111 + .release = easysnd_release, 112 + .ioctl = easysnd_ioctl, 113 + .read = easysnd_read, 114 + .llseek = no_llseek, 115 + }; 116 + struct usb_class_driver easysnd_class = { 117 + .name = "usb/easysnd%d", 118 + .fops = &easysnd_fops, 119 + .minor_base = USB_SKEL_MINOR_BASE, 120 + }; 121 + /****************************************************************************/ 122 + /*--------------------------------------------------------------------------*/ 123 + /* 124 + * IT IS NOT APPROPRIATE FOR easycap_open() TO SUBMIT THE VIDEO URBS HERE, 125 + * BECAUSE THERE WILL ALWAYS BE SUBSEQUENT NEGOTIATION OF TV STANDARD AND 126 + * FORMAT BY IOCTL AND IT IS INADVISABLE TO HAVE THE URBS RUNNING WHILE 127 + * REGISTERS OF THE SA7113H ARE BEING MANIPULATED. 128 + * 129 + * THE SUBMISSION OF VIDEO URBS IS THEREFORE DELAYED UNTIL THE IOCTL COMMAND 130 + * STREAMON IS RECEIVED. 131 + */ 132 + /*--------------------------------------------------------------------------*/ 133 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 134 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 135 + int 136 + easycap_open_noinode(struct file *file) 137 + { 138 + return easycap_open((struct inode *)NULL, file); 139 + } 140 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 141 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 142 + int 143 + easycap_open(struct inode *inode, struct file *file) 144 + { 145 + #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 146 + struct usb_interface *pusb_interface; 147 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 148 + struct usb_device *p; 149 + struct easycap *peasycap; 150 + int i, k, m, rc; 151 + 152 + JOT(4, "\n"); 153 + SAY("==========OPEN=========\n"); 154 + 155 + peasycap = (struct easycap *)NULL; 156 + #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 157 + if ((struct inode *)NULL == inode) { 158 + SAY("ERROR: inode is NULL.\n"); 159 + return -EFAULT; 160 + } 161 + pusb_interface = usb_find_interface(&easycap_usb_driver, iminor(inode)); 162 + if (!pusb_interface) { 163 + SAY("ERROR: pusb_interface is NULL.\n"); 164 + return -EFAULT; 165 + } 166 + peasycap = usb_get_intfdata(pusb_interface); 167 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 168 + #else 169 + for (i = 0; i < video_device_many; i++) { 170 + pvideo_device = pvideo_array[i]; 171 + if ((struct video_device *)NULL != pvideo_device) { 172 + peasycap = (struct easycap *)video_get_drvdata(pvideo_device); 173 + break; 174 + } 175 + } 176 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 177 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 178 + if ((struct easycap *)NULL == peasycap) { 179 + SAY("MISTAKE: peasycap is NULL\n"); 180 + return -EFAULT; 181 + } 182 + file->private_data = peasycap; 183 + /*---------------------------------------------------------------------------*/ 184 + /* 185 + * INITIALIZATION 186 + */ 187 + /*---------------------------------------------------------------------------*/ 188 + JOT(4, "starting initialization\n"); 189 + 190 + for (k = 0; k < FRAME_BUFFER_MANY; k++) { 191 + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) 192 + memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE); 193 + } 194 + p = peasycap->pusb_device; 195 + if ((struct usb_device *)NULL == p) { 196 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 197 + return -EFAULT; 198 + } else { 199 + JOT(16, "0x%08lX=peasycap->pusb_device\n", \ 200 + (long int)peasycap->pusb_device); 201 + } 202 + rc = wakeup_device(peasycap->pusb_device); 203 + if (0 == rc) 204 + JOT(8, "wakeup_device() OK\n"); 205 + else { 206 + SAY("ERROR: wakeup_device() returned %i\n", rc); 207 + return -EFAULT; 208 + } 209 + rc = setup_stk(p); peasycap->input = 0; 210 + if (0 == rc) 211 + JOT(8, "setup_stk() OK\n"); 212 + else { 213 + SAY("ERROR: setup_stk() returned %i\n", rc); 214 + return -EFAULT; 215 + } 216 + rc = setup_saa(p); 217 + if (0 == rc) 218 + JOT(8, "setup_saa() OK\n"); 219 + else { 220 + SAY("ERROR: setup_saa() returned %i\n", rc); 221 + return -EFAULT; 222 + } 223 + rc = check_saa(p); 224 + if (0 == rc) 225 + JOT(8, "check_saa() OK\n"); 226 + else if (-8 < rc) 227 + SAY("check_saa() returned %i\n", rc); 228 + else { 229 + SAY("ERROR: check_saa() returned %i\n", rc); 230 + return -EFAULT; 231 + } 232 + peasycap->standard_offset = -1; 233 + /*---------------------------------------------------------------------------*/ 234 + #if defined(PREFER_NTSC) 235 + 236 + rc = adjust_standard(peasycap, V4L2_STD_NTSC_M); 237 + if (0 == rc) 238 + JOT(8, "adjust_standard(.,NTSC_M) OK\n"); 239 + else { 240 + SAY("ERROR: adjust_standard(.,NTSC_M) returned %i\n", rc); 241 + return -EFAULT; 242 + } 243 + rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \ 244 + false); 245 + if (0 <= rc) 246 + JOT(8, "adjust_format(.,640,480,UYVY) OK\n"); 247 + else { 248 + SAY("ERROR: adjust_format(.,640,480,UYVY) returned %i\n", rc); 249 + return -EFAULT; 250 + } 251 + 252 + #else 253 + 254 + rc = adjust_standard(peasycap, \ 255 + (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \ 256 + V4L2_STD_PAL_I | V4L2_STD_PAL_N)); 257 + if (0 == rc) 258 + JOT(8, "adjust_standard(.,PAL_BGHIN) OK\n"); 259 + else { 260 + SAY("ERROR: adjust_standard(.,PAL_BGHIN) returned %i\n", rc); 261 + return -EFAULT; 262 + } 263 + rc = adjust_format(peasycap, 640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, \ 264 + false); 265 + if (0 <= rc) 266 + JOT(8, "adjust_format(.,640,480,uyvy,false) OK\n"); 267 + else { 268 + SAY("ERROR: adjust_format(.,640,480,uyvy,false) returned %i\n", rc); 269 + return -EFAULT; 270 + } 271 + 272 + #endif /* !PREFER_NTSC*/ 273 + /*---------------------------------------------------------------------------*/ 274 + rc = adjust_brightness(peasycap, -8192); 275 + if (0 != rc) { 276 + SAY("ERROR: adjust_brightness(default) returned %i\n", rc); 277 + return -EFAULT; 278 + } 279 + rc = adjust_contrast(peasycap, -8192); 280 + if (0 != rc) { 281 + SAY("ERROR: adjust_contrast(default) returned %i\n", rc); 282 + return -EFAULT; 283 + } 284 + rc = adjust_saturation(peasycap, -8192); 285 + if (0 != rc) { 286 + SAY("ERROR: adjust_saturation(default) returned %i\n", rc); 287 + return -EFAULT; 288 + } 289 + rc = adjust_hue(peasycap, -8192); 290 + if (0 != rc) { 291 + SAY("ERROR: adjust_hue(default) returned %i\n", rc); 292 + return -EFAULT; 293 + } 294 + /*---------------------------------------------------------------------------*/ 295 + rc = usb_set_interface(peasycap->pusb_device, peasycap->video_interface, \ 296 + peasycap->video_altsetting_on); 297 + if (0 == rc) 298 + JOT(8, "usb_set_interface(.,%i,%i) OK\n", peasycap->video_interface, \ 299 + peasycap->video_altsetting_on); 300 + else { 301 + SAY("ERROR: usb_set_interface() returned %i\n", rc); 302 + return -EFAULT; 303 + } 304 + rc = start_100(p); 305 + if (0 == rc) 306 + JOT(8, "start_100() OK\n"); 307 + else { 308 + SAY("ERROR: start_100() returned %i\n", rc); 309 + return -EFAULT; 310 + } 311 + peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1; 312 + peasycap->video_idle = 0; 313 + peasycap->video_junk = 0; 314 + for (i = 0; i < 180; i++) 315 + peasycap->merit[i] = 0; 316 + peasycap->video_eof = 0; 317 + peasycap->audio_eof = 0; 318 + 319 + do_gettimeofday(&peasycap->timeval7); 320 + 321 + peasycap->fudge = 0; 322 + 323 + JOT(4, "finished initialization\n"); 324 + return 0; 325 + } 326 + /*****************************************************************************/ 327 + int 328 + submit_video_urbs(struct easycap *peasycap) 329 + { 330 + struct data_urb *pdata_urb; 331 + struct urb *purb; 332 + struct list_head *plist_head; 333 + int j, isbad, m, rc; 334 + int isbuf; 335 + 336 + if ((struct list_head *)NULL == peasycap->purb_video_head) { 337 + SAY("ERROR: peasycap->urb_video_head uninitialized\n"); 338 + return -EFAULT; 339 + } 340 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 341 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 342 + return -EFAULT; 343 + } 344 + if (!peasycap->video_isoc_streaming) { 345 + 346 + 347 + 348 + 349 + 350 + 351 + 352 + 353 + JOT(4, "submission of all video urbs\n"); 354 + if (0 != ready_saa(peasycap->pusb_device)) { 355 + SAY("ERROR: not ready to capture after waiting " \ 356 + "one second\n"); 357 + SAY("..... continuing anyway\n"); 358 + } 359 + isbad = 0; m = 0; 360 + list_for_each(plist_head, (peasycap->purb_video_head)) { 361 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 362 + if (NULL != pdata_urb) { 363 + purb = pdata_urb->purb; 364 + if (NULL != purb) { 365 + isbuf = pdata_urb->isbuf; 366 + purb->interval = 1; 367 + purb->dev = peasycap->pusb_device; 368 + purb->pipe = \ 369 + usb_rcvisocpipe(peasycap->pusb_device,\ 370 + peasycap->video_endpointnumber); 371 + purb->transfer_flags = URB_ISO_ASAP; 372 + purb->transfer_buffer = \ 373 + peasycap->video_isoc_buffer[isbuf].pgo; 374 + purb->transfer_buffer_length = \ 375 + peasycap->video_isoc_buffer_size; 376 + purb->complete = easycap_complete; 377 + purb->context = peasycap; 378 + purb->start_frame = 0; 379 + purb->number_of_packets = \ 380 + peasycap->video_isoc_framesperdesc; 381 + 382 + for (j = 0; j < peasycap->\ 383 + video_isoc_framesperdesc; j++) { 384 + purb->iso_frame_desc[j].\ 385 + offset = j * \ 386 + peasycap->\ 387 + video_isoc_maxframesize; 388 + purb->iso_frame_desc[j].\ 389 + length = peasycap->\ 390 + video_isoc_maxframesize; 391 + } 392 + 393 + rc = usb_submit_urb(purb, GFP_KERNEL); 394 + if (0 != rc) { 395 + isbad++; 396 + SAY("ERROR: usb_submit_urb() failed " \ 397 + "for urb with rc:\n"); 398 + switch (rc) { 399 + case -ENOMEM: { 400 + SAY("ENOMEM\n"); 401 + break; 402 + } 403 + case -ENODEV: { 404 + SAY("ENODEV\n"); 405 + break; 406 + } 407 + case -ENXIO: { 408 + SAY("ENXIO\n"); 409 + break; 410 + } 411 + case -EINVAL: { 412 + SAY("EINVAL\n"); 413 + break; 414 + } 415 + case -EAGAIN: { 416 + SAY("EAGAIN\n"); 417 + break; 418 + } 419 + case -EFBIG: { 420 + SAY("EFBIG\n"); 421 + break; 422 + } 423 + case -EPIPE: { 424 + SAY("EPIPE\n"); 425 + break; 426 + } 427 + case -EMSGSIZE: { 428 + SAY("EMSGSIZE\n"); 429 + break; 430 + } 431 + default: { 432 + SAY("unknown error code %i\n",\ 433 + rc); 434 + break; 435 + } 436 + } 437 + } else { 438 + m++; 439 + } 440 + } else { 441 + isbad++; 442 + } 443 + } else { 444 + isbad++; 445 + } 446 + } 447 + if (isbad) { 448 + JOT(4, "attempting cleanup instead of submitting\n"); 449 + list_for_each(plist_head, (peasycap->purb_video_head)) { 450 + pdata_urb = list_entry(plist_head, struct data_urb, \ 451 + list_head); 452 + if (NULL != pdata_urb) { 453 + purb = pdata_urb->purb; 454 + if (NULL != purb) 455 + usb_kill_urb(purb); 456 + } 457 + } 458 + peasycap->video_isoc_streaming = 0; 459 + } else { 460 + peasycap->video_isoc_streaming = 1; 461 + JOT(4, "submitted %i video urbs\n", m); 462 + } 463 + 464 + 465 + 466 + 467 + 468 + 469 + } else { 470 + JOT(4, "already streaming video urbs\n"); 471 + } 472 + return 0; 473 + } 474 + /*****************************************************************************/ 475 + int 476 + kill_video_urbs(struct easycap *peasycap) 477 + { 478 + int m; 479 + struct list_head *plist_head; 480 + struct data_urb *pdata_urb; 481 + 482 + if ((struct easycap *)NULL == peasycap) { 483 + SAY("ERROR: peasycap is NULL\n"); 484 + return -EFAULT; 485 + } 486 + if (peasycap->video_isoc_streaming) { 487 + 488 + 489 + 490 + if ((struct list_head *)NULL != peasycap->purb_video_head) { 491 + peasycap->video_isoc_streaming = 0; 492 + JOT(4, "killing video urbs\n"); 493 + m = 0; 494 + list_for_each(plist_head, (peasycap->purb_video_head)) { 495 + pdata_urb = list_entry(plist_head, struct data_urb, \ 496 + list_head); 497 + if ((struct data_urb *)NULL != pdata_urb) { 498 + if ((struct urb *)NULL != pdata_urb->purb) { 499 + usb_kill_urb(pdata_urb->purb); 500 + m++; 501 + } 502 + } 503 + } 504 + JOT(4, "%i video urbs killed\n", m); 505 + } else { 506 + SAY("ERROR: peasycap->purb_video_head is NULL\n"); 507 + return -EFAULT; 508 + } 509 + } else { 510 + JOT(8, "%i=video_isoc_streaming, no video urbs killed\n", \ 511 + peasycap->video_isoc_streaming); 512 + } 513 + return 0; 514 + } 515 + /****************************************************************************/ 516 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 517 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 518 + int 519 + easycap_release_noinode(struct file *file) 520 + { 521 + return easycap_release((struct inode *)NULL, file); 522 + } 523 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 524 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 525 + /*--------------------------------------------------------------------------*/ 526 + int 527 + easycap_release(struct inode *inode, struct file *file) 528 + { 529 + #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 530 + struct easycap *peasycap; 531 + 532 + JOT(4, "\n"); 533 + 534 + peasycap = (struct easycap *)file->private_data; 535 + if (NULL == peasycap) { 536 + SAY("ERROR: peasycap is NULL.\n"); 537 + SAY("ending unsuccessfully\n"); 538 + return -EFAULT; 539 + } 540 + if (0 != kill_video_urbs(peasycap)) { 541 + SAY("ERROR: kill_video_urbs() failed\n"); 542 + return -EFAULT; 543 + } 544 + JOT(4, "ending successfully\n"); 545 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 546 + #else 547 + # 548 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 549 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 550 + 551 + return 0; 552 + } 553 + /****************************************************************************/ 554 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 555 + #if defined(EASYCAP_IS_VIDEODEV_CLIENT) 556 + int 557 + videodev_release(struct video_device *pvd) 558 + { 559 + struct easycap *peasycap; 560 + int i, j, k; 561 + 562 + JOT(4, "\n"); 563 + 564 + k = 0; 565 + for (i = 0; i < video_device_many; i++) { 566 + pvideo_device = pvideo_array[i]; 567 + if ((struct video_device *)NULL != pvideo_device) { 568 + if (pvd->minor == pvideo_device->minor) { 569 + peasycap = (struct easycap *)\ 570 + video_get_drvdata(pvideo_device); 571 + if ((struct easycap *)NULL == peasycap) { 572 + SAY("ERROR: peasycap is NULL\n"); 573 + SAY("ending unsuccessfully\n"); 574 + return -EFAULT; 575 + } 576 + if (0 != kill_video_urbs(peasycap)) { 577 + SAY("ERROR: kill_video_urbs() failed\n"); 578 + return -EFAULT; 579 + } 580 + JOT(4, "freeing video_device structure: " \ 581 + "/dev/video%i\n", i); 582 + kfree((void *)pvideo_device); 583 + for (j = i; j < (VIDEO_DEVICE_MANY - 1); j++) 584 + pvideo_array[j] = pvideo_array[j + 1]; 585 + video_device_many--; k++; 586 + break; 587 + } 588 + } 589 + } 590 + if (!k) { 591 + SAY("ERROR: lost video_device structure for %i=minor\n", pvd->minor); 592 + SAY("cannot free: may cause memory leak\n"); 593 + SAY("ending unsuccessfully\n"); 594 + return -EFAULT; 595 + } 596 + 597 + JOT(4, "ending successfully\n"); 598 + return 0; 599 + } 600 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 601 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 602 + /****************************************************************************/ 603 + /*--------------------------------------------------------------------------*/ 604 + /* 605 + * THIS FUNCTION IS CALLED FROM WITHIN easycap_usb_disconnect(). 606 + * BY THIS STAGE THE DEVICE HAS ALREADY BEEN PHYSICALLY UNPLUGGED. 607 + * peasycap->pusb_device IS NO LONGER VALID AND SHOULD HAVE BEEN SET TO NULL. 608 + */ 609 + /*---------------------------------------------------------------------------*/ 610 + void 611 + easycap_delete(struct kref *pkref) 612 + { 613 + int k, m, lost; 614 + int allocation_video_urb, allocation_video_page, allocation_video_struct; 615 + int allocation_audio_urb, allocation_audio_page, allocation_audio_struct; 616 + int registered_video, registered_audio; 617 + struct easycap *peasycap; 618 + struct data_urb *pdata_urb; 619 + struct list_head *plist_head, *plist_next; 620 + 621 + JOT(4, "\n"); 622 + 623 + peasycap = container_of(pkref, struct easycap, kref); 624 + if ((struct easycap *)NULL == peasycap) { 625 + SAY("ERROR: peasycap is NULL: cannot perform deletions\n"); 626 + return; 627 + } 628 + /*---------------------------------------------------------------------------*/ 629 + /* 630 + * FREE VIDEO. 631 + */ 632 + /*---------------------------------------------------------------------------*/ 633 + if ((struct list_head *)NULL != peasycap->purb_video_head) { 634 + JOT(4, "freeing video urbs\n"); 635 + m = 0; 636 + list_for_each(plist_head, (peasycap->purb_video_head)) { 637 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 638 + if (NULL == pdata_urb) 639 + JOT(4, "ERROR: pdata_urb is NULL\n"); 640 + else { 641 + if ((struct urb *)NULL != pdata_urb->purb) { 642 + usb_free_urb(pdata_urb->purb); 643 + pdata_urb->purb = (struct urb *)NULL; 644 + peasycap->allocation_video_urb -= 1; 645 + m++; 646 + } 647 + } 648 + } 649 + 650 + JOT(4, "%i video urbs freed\n", m); 651 + /*---------------------------------------------------------------------------*/ 652 + JOT(4, "freeing video data_urb structures.\n"); 653 + m = 0; 654 + list_for_each_safe(plist_head, plist_next, peasycap->purb_video_head) { 655 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 656 + if ((struct data_urb *)NULL != pdata_urb) { 657 + kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL; 658 + peasycap->allocation_video_struct -= \ 659 + sizeof(struct data_urb); 660 + m++; 661 + } 662 + } 663 + JOT(4, "%i video data_urb structures freed\n", m); 664 + JOT(4, "setting peasycap->purb_video_head=NULL\n"); 665 + peasycap->purb_video_head = (struct list_head *)NULL; 666 + } else { 667 + JOT(4, "peasycap->purb_video_head is NULL\n"); 668 + } 669 + /*---------------------------------------------------------------------------*/ 670 + JOT(4, "freeing video isoc buffers.\n"); 671 + m = 0; 672 + for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { 673 + if ((void *)NULL != peasycap->video_isoc_buffer[k].pgo) { 674 + free_pages((unsigned long)\ 675 + (peasycap->video_isoc_buffer[k].pgo), \ 676 + VIDEO_ISOC_ORDER); 677 + peasycap->video_isoc_buffer[k].pgo = (void *)NULL; 678 + peasycap->allocation_video_page -= \ 679 + ((unsigned int)(0x01 << VIDEO_ISOC_ORDER)); 680 + m++; 681 + } 682 + } 683 + JOT(4, "isoc video buffers freed: %i pages\n", m * (0x01 << VIDEO_ISOC_ORDER)); 684 + /*---------------------------------------------------------------------------*/ 685 + JOT(4, "freeing video field buffers.\n"); 686 + lost = 0; 687 + for (k = 0; k < FIELD_BUFFER_MANY; k++) { 688 + for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { 689 + if ((void *)NULL != peasycap->field_buffer[k][m].pgo) { 690 + free_page((unsigned long)\ 691 + (peasycap->field_buffer[k][m].pgo)); 692 + peasycap->field_buffer[k][m].pgo = (void *)NULL; 693 + peasycap->allocation_video_page -= 1; 694 + lost++; 695 + } 696 + } 697 + } 698 + JOT(4, "video field buffers freed: %i pages\n", lost); 699 + /*---------------------------------------------------------------------------*/ 700 + JOT(4, "freeing video frame buffers.\n"); 701 + lost = 0; 702 + for (k = 0; k < FRAME_BUFFER_MANY; k++) { 703 + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { 704 + if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) { 705 + free_page((unsigned long)\ 706 + (peasycap->frame_buffer[k][m].pgo)); 707 + peasycap->frame_buffer[k][m].pgo = (void *)NULL; 708 + peasycap->allocation_video_page -= 1; 709 + lost++; 710 + } 711 + } 712 + } 713 + JOT(4, "video frame buffers freed: %i pages\n", lost); 714 + /*---------------------------------------------------------------------------*/ 715 + /* 716 + * FREE AUDIO. 717 + */ 718 + /*---------------------------------------------------------------------------*/ 719 + if ((struct list_head *)NULL != peasycap->purb_audio_head) { 720 + JOT(4, "freeing audio urbs\n"); 721 + m = 0; 722 + list_for_each(plist_head, (peasycap->purb_audio_head)) { 723 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 724 + if (NULL == pdata_urb) 725 + JOT(4, "ERROR: pdata_urb is NULL\n"); 726 + else { 727 + if ((struct urb *)NULL != pdata_urb->purb) { 728 + usb_free_urb(pdata_urb->purb); 729 + pdata_urb->purb = (struct urb *)NULL; 730 + peasycap->allocation_audio_urb -= 1; 731 + m++; 732 + } 733 + } 734 + } 735 + JOT(4, "%i audio urbs freed\n", m); 736 + /*---------------------------------------------------------------------------*/ 737 + JOT(4, "freeing audio data_urb structures.\n"); 738 + m = 0; 739 + list_for_each_safe(plist_head, plist_next, peasycap->purb_audio_head) { 740 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 741 + if ((struct data_urb *)NULL != pdata_urb) { 742 + kfree(pdata_urb); pdata_urb = (struct data_urb *)NULL; 743 + peasycap->allocation_audio_struct -= \ 744 + sizeof(struct data_urb); 745 + m++; 746 + } 747 + } 748 + JOT(4, "%i audio data_urb structures freed\n", m); 749 + JOT(4, "setting peasycap->purb_audio_head=NULL\n"); 750 + peasycap->purb_audio_head = (struct list_head *)NULL; 751 + } else { 752 + JOT(4, "peasycap->purb_audio_head is NULL\n"); 753 + } 754 + /*---------------------------------------------------------------------------*/ 755 + JOT(4, "freeing audio isoc buffers.\n"); 756 + m = 0; 757 + for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { 758 + if ((void *)NULL != peasycap->audio_isoc_buffer[k].pgo) { 759 + free_pages((unsigned long)\ 760 + (peasycap->audio_isoc_buffer[k].pgo), \ 761 + AUDIO_ISOC_ORDER); 762 + peasycap->audio_isoc_buffer[k].pgo = (void *)NULL; 763 + peasycap->allocation_audio_page -= \ 764 + ((unsigned int)(0x01 << AUDIO_ISOC_ORDER)); 765 + m++; 766 + } 767 + } 768 + JOT(4, "easysnd_delete(): isoc audio buffers freed: %i pages\n", \ 769 + m * (0x01 << AUDIO_ISOC_ORDER)); 770 + /*---------------------------------------------------------------------------*/ 771 + JOT(4, "freeing audio buffers.\n"); 772 + lost = 0; 773 + for (k = 0; k < audio_buffer_page_many; k++) { 774 + if ((void *)NULL != peasycap->audio_buffer[k].pgo) { 775 + free_page((unsigned long)(peasycap->audio_buffer[k].pgo)); 776 + peasycap->audio_buffer[k].pgo = (void *)NULL; 777 + peasycap->allocation_audio_page -= 1; 778 + lost++; 779 + } 780 + } 781 + JOT(4, "easysnd_delete(): audio buffers freed: %i pages\n", lost); 782 + /*---------------------------------------------------------------------------*/ 783 + JOT(4, "freeing easycap structure.\n"); 784 + allocation_video_urb = peasycap->allocation_video_urb; 785 + allocation_video_page = peasycap->allocation_video_page; 786 + allocation_video_struct = peasycap->allocation_video_struct; 787 + registered_video = peasycap->registered_video; 788 + allocation_audio_urb = peasycap->allocation_audio_urb; 789 + allocation_audio_page = peasycap->allocation_audio_page; 790 + allocation_audio_struct = peasycap->allocation_audio_struct; 791 + registered_audio = peasycap->registered_audio; 792 + m = 0; 793 + if ((struct easycap *)NULL != peasycap) { 794 + kfree(peasycap); peasycap = (struct easycap *)NULL; 795 + allocation_video_struct -= sizeof(struct easycap); 796 + m++; 797 + } 798 + JOT(4, "%i easycap structure freed\n", m); 799 + /*---------------------------------------------------------------------------*/ 800 + 801 + SAY("%8i= video urbs after all deletions\n", allocation_video_urb); 802 + SAY("%8i= video pages after all deletions\n", allocation_video_page); 803 + SAY("%8i= video structs after all deletions\n", allocation_video_struct); 804 + SAY("%8i= video devices after all deletions\n", registered_video); 805 + SAY("%8i= audio urbs after all deletions\n", allocation_audio_urb); 806 + SAY("%8i= audio pages after all deletions\n", allocation_audio_page); 807 + SAY("%8i= audio structs after all deletions\n", allocation_audio_struct); 808 + SAY("%8i= audio devices after all deletions\n", registered_audio); 809 + 810 + JOT(4, "ending.\n"); 811 + return; 812 + } 813 + /*****************************************************************************/ 814 + unsigned int easycap_poll(struct file *file, poll_table *wait) 815 + { 816 + struct easycap *peasycap; 817 + 818 + JOT(8, "\n"); 819 + 820 + if (NULL == ((poll_table *)wait)) 821 + JOT(8, "WARNING: poll table pointer is NULL ... continuing\n"); 822 + if (NULL == ((struct file *)file)) { 823 + SAY("ERROR: file pointer is NULL\n"); 824 + return -EFAULT; 825 + } 826 + peasycap = (struct easycap *)file->private_data; 827 + if (NULL == peasycap) { 828 + SAY("ERROR: peasycap is NULL\n"); 829 + return -EFAULT; 830 + } 831 + peasycap->polled = 1; 832 + 833 + if (0 == easycap_dqbuf(peasycap, 0)) 834 + return POLLIN | POLLRDNORM; 835 + else 836 + return POLLERR; 837 + 838 + } 839 + /*****************************************************************************/ 840 + /*---------------------------------------------------------------------------*/ 841 + /* 842 + * IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING. 843 + */ 844 + /*---------------------------------------------------------------------------*/ 845 + int 846 + easycap_dqbuf(struct easycap *peasycap, int mode) 847 + { 848 + int miss, rc; 849 + 850 + JOT(8, "\n"); 851 + 852 + if (NULL == peasycap) { 853 + SAY("ERROR: peasycap is NULL\n"); 854 + return -EFAULT; 855 + } 856 + /*---------------------------------------------------------------------------*/ 857 + /* 858 + * WAIT FOR FIELD 0 859 + */ 860 + /*---------------------------------------------------------------------------*/ 861 + miss = 0; 862 + if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) 863 + return -ERESTARTSYS; 864 + while ((peasycap->field_read == peasycap->field_fill) || \ 865 + (0 != (0xFF00 & peasycap->field_buffer\ 866 + [peasycap->field_read][0].kount)) || \ 867 + (0 != (0x00FF & peasycap->field_buffer\ 868 + [peasycap->field_read][0].kount))) { 869 + mutex_unlock(&(peasycap->mutex_mmap_video[0])); 870 + 871 + if (mode) 872 + return -EAGAIN; 873 + 874 + JOT(8, "first wait on wq_video, " \ 875 + "%i=field_read %i=field_fill\n", \ 876 + peasycap->field_read, peasycap->field_fill); 877 + 878 + msleep(1); 879 + if (0 != (wait_event_interruptible(peasycap->wq_video, \ 880 + (peasycap->video_idle || peasycap->video_eof || \ 881 + ((peasycap->field_read != peasycap->field_fill) && \ 882 + (0 == (0xFF00 & peasycap->field_buffer\ 883 + [peasycap->field_read][0].kount)) && \ 884 + (0 == (0x00FF & peasycap->field_buffer\ 885 + [peasycap->field_read][0].kount))))))){ 886 + SAY("aborted by signal\n"); 887 + return -EIO; 888 + } 889 + if (peasycap->video_idle) { 890 + JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle); 891 + return -EIO; 892 + } 893 + if (peasycap->video_eof) { 894 + JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof); 895 + debrief(peasycap); 896 + kill_video_urbs(peasycap); 897 + return -EIO; 898 + } 899 + miss++; 900 + if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) 901 + return -ERESTARTSYS; 902 + } 903 + mutex_unlock(&(peasycap->mutex_mmap_video[0])); 904 + JOT(8, "first awakening on wq_video after %i waits\n", miss); 905 + 906 + rc = field2frame(peasycap); 907 + if (0 != rc) 908 + SAY("ERROR: field2frame() returned %i\n", rc); 909 + 910 + if (true == peasycap->offerfields) { 911 + peasycap->frame_read = peasycap->frame_fill; 912 + (peasycap->frame_fill)++; 913 + if (peasycap->frame_buffer_many <= peasycap->frame_fill) 914 + peasycap->frame_fill = 0; 915 + 916 + if (0x01 & easycap_standard[peasycap->standard_offset].mask) { 917 + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ 918 + V4L2_FIELD_BOTTOM; 919 + } else { 920 + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ 921 + V4L2_FIELD_TOP; 922 + } 923 + JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read); 924 + JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill); 925 + } 926 + /*---------------------------------------------------------------------------*/ 927 + /* 928 + * WAIT FOR FIELD 1 929 + */ 930 + /*---------------------------------------------------------------------------*/ 931 + miss = 0; 932 + if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) 933 + return -ERESTARTSYS; 934 + while ((peasycap->field_read == peasycap->field_fill) || \ 935 + (0 != (0xFF00 & peasycap->field_buffer\ 936 + [peasycap->field_read][0].kount)) || \ 937 + (0 == (0x00FF & peasycap->field_buffer\ 938 + [peasycap->field_read][0].kount))) { 939 + mutex_unlock(&(peasycap->mutex_mmap_video[0])); 940 + 941 + if (mode) 942 + return -EAGAIN; 943 + 944 + JOT(8, "second wait on wq_video, " \ 945 + "%i=field_read %i=field_fill\n", \ 946 + peasycap->field_read, peasycap->field_fill); 947 + msleep(1); 948 + if (0 != (wait_event_interruptible(peasycap->wq_video, \ 949 + (peasycap->video_idle || peasycap->video_eof || \ 950 + ((peasycap->field_read != peasycap->field_fill) && \ 951 + (0 == (0xFF00 & peasycap->field_buffer\ 952 + [peasycap->field_read][0].kount)) && \ 953 + (0 != (0x00FF & peasycap->field_buffer\ 954 + [peasycap->field_read][0].kount))))))){ 955 + SAY("aborted by signal\n"); 956 + return -EIO; 957 + } 958 + if (peasycap->video_idle) { 959 + JOT(8, "%i=peasycap->video_idle\n", peasycap->video_idle); 960 + return -EIO; 961 + } 962 + if (peasycap->video_eof) { 963 + JOT(8, "%i=peasycap->video_eof\n", peasycap->video_eof); 964 + debrief(peasycap); 965 + kill_video_urbs(peasycap); 966 + return -EIO; 967 + } 968 + miss++; 969 + if (mutex_lock_interruptible(&(peasycap->mutex_mmap_video[0]))) 970 + return -ERESTARTSYS; 971 + } 972 + mutex_unlock(&(peasycap->mutex_mmap_video[0])); 973 + JOT(8, "second awakening on wq_video after %i waits\n", miss); 974 + 975 + rc = field2frame(peasycap); 976 + if (0 != rc) 977 + SAY("ERROR: field2frame() returned %i\n", rc); 978 + 979 + peasycap->frame_read = peasycap->frame_fill; 980 + peasycap->queued[peasycap->frame_read] = 0; 981 + peasycap->done[peasycap->frame_read] = V4L2_BUF_FLAG_DONE; 982 + 983 + (peasycap->frame_fill)++; 984 + if (peasycap->frame_buffer_many <= peasycap->frame_fill) 985 + peasycap->frame_fill = 0; 986 + 987 + if (0x01 & easycap_standard[peasycap->standard_offset].mask) { 988 + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ 989 + V4L2_FIELD_TOP; 990 + } else { 991 + peasycap->frame_buffer[peasycap->frame_read][0].kount = \ 992 + V4L2_FIELD_BOTTOM; 993 + } 994 + 995 + JOT(8, "setting: %i=peasycap->frame_read\n", peasycap->frame_read); 996 + JOT(8, "bumped to: %i=peasycap->frame_fill\n", peasycap->frame_fill); 997 + 998 + return 0; 999 + } 1000 + /*****************************************************************************/ 1001 + /*---------------------------------------------------------------------------*/ 1002 + /* 1003 + * BY DEFINITION, odd IS true FOR THE FIELD OCCUPYING LINES 1,3,5,...,479 1004 + * odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478 1005 + * 1006 + * WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH 1007 + * odd==false IS TRANSFERRED TO THE FRAME BUFFER. 1008 + * 1009 + * THE BOOLEAN PARAMETER offerfields IS true ONLY WHEN THE USER PROGRAM 1010 + * CHOOSES THE OPTION V4L2_FIELD_ALTERNATE. NO USERSPACE PROGRAM TESTED 1011 + * TO DATE HAS DONE THIS. BUGS ARE LIKELY. 1012 + */ 1013 + /*---------------------------------------------------------------------------*/ 1014 + int 1015 + field2frame(struct easycap *peasycap) 1016 + { 1017 + static struct timeval timeval0; 1018 + struct timeval timeval; 1019 + long long int above, below; 1020 + __u32 remainder; 1021 + struct signed_div_result sdr; 1022 + 1023 + void *pex, *pad; 1024 + int kex, kad, mex, mad, rex, rad, rad2; 1025 + int c2, c3, w2, w3, cz, wz; 1026 + int rc, bytesperpixel, multiplier, much, more, over, rump, caches; 1027 + __u8 mask, margin; 1028 + bool odd, isuy, decimatepixel, offerfields; 1029 + 1030 + JOT(8, "===== parity %i, field buffer %i --> frame buffer %i\n", \ 1031 + peasycap->field_buffer[peasycap->field_read][0].kount,\ 1032 + peasycap->field_read, peasycap->frame_fill); 1033 + JOT(8, "===== %i=bytesperpixel\n", peasycap->bytesperpixel); 1034 + if (true == peasycap->offerfields) 1035 + JOT(8, "===== offerfields\n"); 1036 + 1037 + /*---------------------------------------------------------------------------*/ 1038 + /* 1039 + * REJECT OR CLEAN BAD FIELDS 1040 + */ 1041 + /*---------------------------------------------------------------------------*/ 1042 + if (peasycap->field_read == peasycap->field_fill) { 1043 + SAY("ERROR: on entry, still filling field buffer %i\n", \ 1044 + peasycap->field_read); 1045 + return 0; 1046 + } 1047 + #if defined(EASYCAP_TESTCARD) 1048 + easycap_testcard(peasycap, peasycap->field_read); 1049 + #else 1050 + if (0 != (0x0400 & peasycap->field_buffer[peasycap->field_read][0].kount)) 1051 + easycap_testcard(peasycap, peasycap->field_read); 1052 + #endif /*EASYCAP_TESTCARD*/ 1053 + /*---------------------------------------------------------------------------*/ 1054 + 1055 + offerfields = peasycap->offerfields; 1056 + bytesperpixel = peasycap->bytesperpixel; 1057 + decimatepixel = peasycap->decimatepixel; 1058 + 1059 + if ((2 != bytesperpixel) && \ 1060 + (3 != bytesperpixel) && \ 1061 + (4 != bytesperpixel)) { 1062 + SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel); 1063 + return -EFAULT; 1064 + } 1065 + if (true == decimatepixel) 1066 + multiplier = 2; 1067 + else 1068 + multiplier = 1; 1069 + 1070 + w2 = 2 * multiplier * (peasycap->width); 1071 + w3 = bytesperpixel * \ 1072 + multiplier * \ 1073 + (peasycap->width); 1074 + wz = multiplier * \ 1075 + (peasycap->height) * \ 1076 + multiplier * \ 1077 + (peasycap->width); 1078 + 1079 + kex = peasycap->field_read; mex = 0; 1080 + kad = peasycap->frame_fill; mad = 0; 1081 + 1082 + pex = peasycap->field_buffer[kex][0].pgo; rex = PAGE_SIZE; 1083 + pad = peasycap->frame_buffer[kad][0].pgo; rad = PAGE_SIZE; 1084 + if (peasycap->field_buffer[kex][0].kount) 1085 + odd = true; 1086 + else 1087 + odd = false; 1088 + 1089 + if ((true == odd) && (false == offerfields) &&(false == decimatepixel)) { 1090 + JOT(8, " initial skipping %4i bytes p.%4i\n", \ 1091 + w3/multiplier, mad); 1092 + pad += (w3 / multiplier); rad -= (w3 / multiplier); 1093 + } 1094 + isuy = true; 1095 + mask = 0; rump = 0; caches = 0; 1096 + 1097 + cz = 0; 1098 + while (cz < wz) { 1099 + /*-------------------------------------------------------------------*/ 1100 + /* 1101 + ** PROCESS ONE LINE OF FRAME AT FULL RESOLUTION: 1102 + ** READ w2 BYTES FROM FIELD BUFFER, 1103 + ** WRITE w3 BYTES TO FRAME BUFFER 1104 + **/ 1105 + /*-------------------------------------------------------------------*/ 1106 + if (false == decimatepixel) { 1107 + over = w2; 1108 + do { 1109 + much = over; more = 0; margin = 0; mask = 0x00; 1110 + if (rex < much) 1111 + much = rex; 1112 + rump = 0; 1113 + 1114 + if (much % 2) { 1115 + SAY("MISTAKE: much is odd\n"); 1116 + return -EFAULT; 1117 + } 1118 + 1119 + more = (bytesperpixel * \ 1120 + much) / 2; 1121 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1122 + if (1 < bytesperpixel) { 1123 + if ((rad * \ 1124 + 2) < (much * \ 1125 + bytesperpixel)) { 1126 + /* 1127 + ** INJUDICIOUS ALTERATION OF THIS 1128 + ** BLOCK WILL CAUSE BREAKAGE. 1129 + ** BEWARE. 1130 + **/ 1131 + rad2 = rad + bytesperpixel - 1; 1132 + much = ((((2 * \ 1133 + rad2)/bytesperpixel)/2) * 2); 1134 + rump = ((bytesperpixel * \ 1135 + much) / 2) - rad; 1136 + more = rad; 1137 + } 1138 + mask = (__u8)rump; 1139 + margin = 0; 1140 + if (much == rex) { 1141 + mask |= 0x04; 1142 + if ((mex + 1) < FIELD_BUFFER_SIZE/ \ 1143 + PAGE_SIZE) { 1144 + margin = *((__u8 *)(peasycap->\ 1145 + field_buffer\ 1146 + [kex][mex + 1].pgo)); 1147 + } else 1148 + mask |= 0x08; 1149 + } 1150 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1151 + } else { 1152 + SAY("MISTAKE: %i=bytesperpixel\n", \ 1153 + bytesperpixel); 1154 + return -EFAULT; 1155 + } 1156 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1157 + if (rump) 1158 + caches++; 1159 + 1160 + rc = redaub(peasycap, pad, pex, much, more, \ 1161 + mask, margin, isuy); 1162 + if (0 > rc) { 1163 + SAY("ERROR: redaub() failed\n"); 1164 + return -EFAULT; 1165 + } 1166 + if (much % 4) { 1167 + if (isuy) 1168 + isuy = false; 1169 + else 1170 + isuy = true; 1171 + } 1172 + over -= much; cz += much; 1173 + pex += much; rex -= much; 1174 + if (!rex) { 1175 + mex++; 1176 + pex = peasycap->field_buffer[kex][mex].pgo; 1177 + rex = PAGE_SIZE; 1178 + } 1179 + pad += more; 1180 + rad -= more; 1181 + if (!rad) { 1182 + mad++; 1183 + pad = peasycap->frame_buffer[kad][mad].pgo; 1184 + rad = PAGE_SIZE; 1185 + if (rump) { 1186 + pad += rump; 1187 + rad -= rump; 1188 + } 1189 + } 1190 + } while (over); 1191 + /*---------------------------------------------------------------------------*/ 1192 + /* 1193 + * SKIP w3 BYTES IN TARGET FRAME BUFFER, 1194 + * UNLESS IT IS THE LAST LINE OF AN ODD FRAME 1195 + */ 1196 + /*---------------------------------------------------------------------------*/ 1197 + if (((false == odd) || (cz != wz))&&(false == offerfields)) { 1198 + over = w3; 1199 + do { 1200 + if (!rad) { 1201 + mad++; 1202 + pad = peasycap->frame_buffer\ 1203 + [kad][mad].pgo; 1204 + rad = PAGE_SIZE; 1205 + } 1206 + more = over; 1207 + if (rad < more) 1208 + more = rad; 1209 + over -= more; 1210 + pad += more; 1211 + rad -= more; 1212 + } while (over); 1213 + } 1214 + /*---------------------------------------------------------------------------*/ 1215 + /* 1216 + * PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION: 1217 + * ONLY IF false==odd, 1218 + * READ w2 BYTES FROM FIELD BUFFER, 1219 + * WRITE w3 / 2 BYTES TO FRAME BUFFER 1220 + */ 1221 + /*---------------------------------------------------------------------------*/ 1222 + } else if (false == odd) { 1223 + over = w2; 1224 + do { 1225 + much = over; more = 0; margin = 0; mask = 0x00; 1226 + if (rex < much) 1227 + much = rex; 1228 + rump = 0; 1229 + 1230 + if (much % 2) { 1231 + SAY("MISTAKE: much is odd\n"); 1232 + return -EFAULT; 1233 + } 1234 + 1235 + more = (bytesperpixel * \ 1236 + much) / 4; 1237 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1238 + if (1 < bytesperpixel) { 1239 + if ((rad * 4) < (much * \ 1240 + bytesperpixel)) { 1241 + /* 1242 + ** INJUDICIOUS ALTERATION OF THIS 1243 + ** BLOCK WILL CAUSE BREAKAGE. 1244 + ** BEWARE. 1245 + **/ 1246 + rad2 = rad + bytesperpixel - 1; 1247 + much = ((((2 * rad2)/bytesperpixel)/2)\ 1248 + * 4); 1249 + rump = ((bytesperpixel * \ 1250 + much) / 4) - rad; 1251 + more = rad; 1252 + } 1253 + mask = (__u8)rump; 1254 + margin = 0; 1255 + if (much == rex) { 1256 + mask |= 0x04; 1257 + if ((mex + 1) < FIELD_BUFFER_SIZE/ \ 1258 + PAGE_SIZE) { 1259 + margin = *((__u8 *)(peasycap->\ 1260 + field_buffer\ 1261 + [kex][mex + 1].pgo)); 1262 + } 1263 + else 1264 + mask |= 0x08; 1265 + } 1266 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1267 + } else { 1268 + SAY("MISTAKE: %i=bytesperpixel\n", \ 1269 + bytesperpixel); 1270 + return -EFAULT; 1271 + } 1272 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1273 + if (rump) 1274 + caches++; 1275 + 1276 + rc = redaub(peasycap, pad, pex, much, more, \ 1277 + mask, margin, isuy); 1278 + if (0 > rc) { 1279 + SAY("ERROR: redaub() failed\n"); 1280 + return -EFAULT; 1281 + } 1282 + over -= much; cz += much; 1283 + pex += much; rex -= much; 1284 + if (!rex) { 1285 + mex++; 1286 + pex = peasycap->field_buffer[kex][mex].pgo; 1287 + rex = PAGE_SIZE; 1288 + } 1289 + pad += more; 1290 + rad -= more; 1291 + if (!rad) { 1292 + mad++; 1293 + pad = peasycap->frame_buffer[kad][mad].pgo; 1294 + rad = PAGE_SIZE; 1295 + if (rump) { 1296 + pad += rump; 1297 + rad -= rump; 1298 + } 1299 + } 1300 + } while (over); 1301 + /*---------------------------------------------------------------------------*/ 1302 + /* 1303 + * OTHERWISE JUST 1304 + * READ w2 BYTES FROM FIELD BUFFER AND DISCARD THEM 1305 + */ 1306 + /*---------------------------------------------------------------------------*/ 1307 + } else { 1308 + over = w2; 1309 + do { 1310 + if (!rex) { 1311 + mex++; 1312 + pex = peasycap->field_buffer[kex][mex].pgo; 1313 + rex = PAGE_SIZE; 1314 + } 1315 + much = over; 1316 + if (rex < much) 1317 + much = rex; 1318 + over -= much; 1319 + cz += much; 1320 + pex += much; 1321 + rex -= much; 1322 + } while (over); 1323 + } 1324 + } 1325 + /*---------------------------------------------------------------------------*/ 1326 + /* 1327 + * SANITY CHECKS 1328 + */ 1329 + /*---------------------------------------------------------------------------*/ 1330 + c2 = (mex + 1)*PAGE_SIZE - rex; 1331 + if (cz != c2) 1332 + SAY("ERROR: discrepancy %i in bytes read\n", c2 - cz); 1333 + c3 = (mad + 1)*PAGE_SIZE - rad; 1334 + 1335 + if (false == decimatepixel) { 1336 + if (bytesperpixel * \ 1337 + cz != c3) \ 1338 + SAY("ERROR: discrepancy %i in bytes written\n", \ 1339 + c3 - (bytesperpixel * \ 1340 + cz)); 1341 + } else { 1342 + if (false == odd) { 1343 + if (bytesperpixel * \ 1344 + cz != (4 * c3)) 1345 + SAY("ERROR: discrepancy %i in bytes written\n", \ 1346 + (2*c3)-(bytesperpixel * \ 1347 + cz)); 1348 + } else { 1349 + if (0 != c3) 1350 + SAY("ERROR: discrepancy %i " \ 1351 + "in bytes written\n", c3); 1352 + } 1353 + } 1354 + if (rump) 1355 + SAY("ERROR: undischarged cache at end of line in frame buffer\n"); 1356 + 1357 + JOT(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3); 1358 + JOT(8, "===== field2frame(): %i=mad %i=rad\n", mad, rad); 1359 + 1360 + if (true == odd) 1361 + JOT(8, "+++++ field2frame(): frame buffer %i is full\n", kad); 1362 + 1363 + if (peasycap->field_read == peasycap->field_fill) 1364 + SAY("WARNING: on exit, filling field buffer %i\n", \ 1365 + peasycap->field_read); 1366 + /*---------------------------------------------------------------------------*/ 1367 + /* 1368 + * CALCULATE VIDEO STREAMING RATE 1369 + */ 1370 + /*---------------------------------------------------------------------------*/ 1371 + do_gettimeofday(&timeval); 1372 + if (timeval0.tv_sec) { 1373 + below = ((long long int)(1000000)) * \ 1374 + ((long long int)(timeval.tv_sec - timeval0.tv_sec)) + \ 1375 + (long long int)(timeval.tv_usec - timeval0.tv_usec); 1376 + above = (long long int)1000000; 1377 + 1378 + sdr = signed_div(above, below); 1379 + above = sdr.quotient; 1380 + remainder = (__u32)sdr.remainder; 1381 + 1382 + JOT(8, "video streaming at %3lli.%03i fields per second\n", above, \ 1383 + (remainder/1000)); 1384 + } 1385 + timeval0 = timeval; 1386 + 1387 + if (caches) 1388 + JOT(8, "%i=caches\n", caches); 1389 + return 0; 1390 + } 1391 + /*****************************************************************************/ 1392 + struct signed_div_result 1393 + signed_div(long long int above, long long int below) 1394 + { 1395 + struct signed_div_result sdr; 1396 + 1397 + if (((0 <= above) && (0 <= below)) || ((0 > above) && (0 > below))) { 1398 + sdr.remainder = (unsigned long long int) do_div(above, below); 1399 + sdr.quotient = (long long int) above; 1400 + } else { 1401 + if (0 > above) 1402 + above = -above; 1403 + if (0 > below) 1404 + below = -below; 1405 + sdr.remainder = (unsigned long long int) do_div(above, below); 1406 + sdr.quotient = -((long long int) above); 1407 + } 1408 + return sdr; 1409 + } 1410 + /*****************************************************************************/ 1411 + /*---------------------------------------------------------------------------*/ 1412 + /* 1413 + * DECIMATION AND COLOURSPACE CONVERSION. 1414 + * 1415 + * THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE 1416 + * AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE. 1417 + * THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST 1418 + * ALSO ENSURE THAT much IS EVEN. 1419 + * 1420 + * much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN 1421 + * IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION. 1422 + * 1423 + * mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS: 1424 + * 0x03 & mask = number of bytes to be written to cache instead of to 1425 + * frame buffer 1426 + * 0x04 & mask => use argument margin to set the chrominance for last pixel 1427 + * 0x08 & mask => do not set the chrominance for last pixel 1428 + * 1429 + * YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601. 1430 + * 1431 + * THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID 1432 + * INEFFICIENT SWITCHING INSIDE INNER LOOPS. REARRANGING THE LOGIC TO 1433 + * REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE. BEWARE. 1434 + */ 1435 + /*---------------------------------------------------------------------------*/ 1436 + int 1437 + redaub(struct easycap *peasycap, void *pad, void *pex, int much, int more, \ 1438 + __u8 mask, __u8 margin, bool isuy) 1439 + { 1440 + static __s32 ay[256], bu[256], rv[256], gu[256], gv[256]; 1441 + static __u8 cache[8], *pcache; 1442 + __u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr; 1443 + int bytesperpixel; 1444 + bool byteswaporder, decimatepixel, last; 1445 + int j, rump; 1446 + __s32 s32; 1447 + 1448 + if (much % 2) { 1449 + SAY("MISTAKE: much is odd\n"); 1450 + return -EFAULT; 1451 + } 1452 + bytesperpixel = peasycap->bytesperpixel; 1453 + byteswaporder = peasycap->byteswaporder; 1454 + decimatepixel = peasycap->decimatepixel; 1455 + 1456 + /*---------------------------------------------------------------------------*/ 1457 + if (!bu[255]) { 1458 + for (j = 0; j < 112; j++) { 1459 + s32 = (0xFF00 & (453 * j)) >> 8; 1460 + bu[j + 128] = s32; bu[127 - j] = -s32; 1461 + s32 = (0xFF00 & (359 * j)) >> 8; 1462 + rv[j + 128] = s32; rv[127 - j] = -s32; 1463 + s32 = (0xFF00 & (88 * j)) >> 8; 1464 + gu[j + 128] = s32; gu[127 - j] = -s32; 1465 + s32 = (0xFF00 & (183 * j)) >> 8; 1466 + gv[j + 128] = s32; gv[127 - j] = -s32; 1467 + } 1468 + for (j = 0; j < 16; j++) { 1469 + bu[j] = bu[16]; rv[j] = rv[16]; 1470 + gu[j] = gu[16]; gv[j] = gv[16]; 1471 + } 1472 + for (j = 240; j < 256; j++) { 1473 + bu[j] = bu[239]; rv[j] = rv[239]; 1474 + gu[j] = gu[239]; gv[j] = gv[239]; 1475 + } 1476 + for (j = 16; j < 236; j++) 1477 + ay[j] = j; 1478 + for (j = 0; j < 16; j++) 1479 + ay[j] = ay[16]; 1480 + for (j = 236; j < 256; j++) 1481 + ay[j] = ay[235]; 1482 + JOT(8, "lookup tables are prepared\n"); 1483 + } 1484 + if ((__u8 *)NULL == pcache) 1485 + pcache = &cache[0]; 1486 + /*---------------------------------------------------------------------------*/ 1487 + /* 1488 + * TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER 1489 + */ 1490 + /*---------------------------------------------------------------------------*/ 1491 + if (!pcache) { 1492 + SAY("MISTAKE: pcache is NULL\n"); 1493 + return -EFAULT; 1494 + } 1495 + 1496 + if (pcache != &cache[0]) 1497 + JOT(16, "cache has %i bytes\n", (int)(pcache - &cache[0])); 1498 + p2 = &cache[0]; 1499 + p3 = (__u8 *)pad - (int)(pcache - &cache[0]); 1500 + while (p2 < pcache) { 1501 + *p3++ = *p2; p2++; 1502 + } 1503 + pcache = &cache[0]; 1504 + if (p3 != pad) { 1505 + SAY("MISTAKE: pointer misalignment\n"); 1506 + return -EFAULT; 1507 + } 1508 + /*---------------------------------------------------------------------------*/ 1509 + rump = (int)(0x03 & mask); 1510 + u = 0; v = 0; 1511 + p2 = (__u8 *)pex; pz = p2 + much; pr = p3 + more; last = false; 1512 + p2++; 1513 + 1514 + if (true == isuy) 1515 + u = *(p2 - 1); 1516 + else 1517 + v = *(p2 - 1); 1518 + 1519 + if (rump) 1520 + JOT(16, "%4i=much %4i=more %i=rump\n", much, more, rump); 1521 + 1522 + /*---------------------------------------------------------------------------*/ 1523 + switch (bytesperpixel) { 1524 + case 2: { 1525 + if (false == decimatepixel) { 1526 + memcpy(pad, pex, (size_t)much); 1527 + if (false == byteswaporder) 1528 + /*---------------------------------------------------*/ 1529 + /* 1530 + ** UYVY 1531 + */ 1532 + /*---------------------------------------------------*/ 1533 + return 0; 1534 + else { 1535 + /*---------------------------------------------------*/ 1536 + /* 1537 + ** YUYV 1538 + */ 1539 + /*---------------------------------------------------*/ 1540 + p3 = (__u8 *)pad; pz = p3 + much; 1541 + while (pz > p3) { 1542 + c = *p3; 1543 + *p3 = *(p3 + 1); 1544 + *(p3 + 1) = c; 1545 + p3 += 2; 1546 + } 1547 + return 0; 1548 + } 1549 + } else { 1550 + if (false == byteswaporder) { 1551 + /*---------------------------------------------------*/ 1552 + /* 1553 + ** UYVY DECIMATED 1554 + */ 1555 + /*---------------------------------------------------*/ 1556 + p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much; 1557 + while (pz > p2) { 1558 + *p3 = *p2; 1559 + *(p3 + 1) = *(p2 + 1); 1560 + *(p3 + 2) = *(p2 + 2); 1561 + *(p3 + 3) = *(p2 + 3); 1562 + p3 += 4; p2 += 8; 1563 + } 1564 + return 0; 1565 + } else { 1566 + /*---------------------------------------------------*/ 1567 + /* 1568 + ** YUYV DECIMATED 1569 + **/ 1570 + /*---------------------------------------------------*/ 1571 + p2 = (__u8 *)pex; p3 = (__u8 *)pad; pz = p2 + much; 1572 + while (pz > p2) { 1573 + *p3 = *(p2 + 1); 1574 + *(p3 + 1) = *p2; 1575 + *(p3 + 2) = *(p2 + 3); 1576 + *(p3 + 3) = *(p2 + 2); 1577 + p3 += 4; p2 += 8; 1578 + } 1579 + return 0; 1580 + } 1581 + } 1582 + break; 1583 + } 1584 + case 3: 1585 + { 1586 + if (false == decimatepixel) { 1587 + if (false == byteswaporder) { 1588 + /*---------------------------------------------------*/ 1589 + /* 1590 + ** RGB 1591 + **/ 1592 + /*---------------------------------------------------*/ 1593 + while (pz > p2) { 1594 + if (pr <= (p3 + bytesperpixel)) 1595 + last = true; 1596 + else 1597 + last = false; 1598 + y = *p2; 1599 + if ((true == last) && (0x0C & mask)) { 1600 + if (0x04 & mask) { 1601 + if (true == isuy) 1602 + v = margin; 1603 + else 1604 + u = margin; 1605 + } else 1606 + if (0x08 & mask) 1607 + ; 1608 + } else { 1609 + if (true == isuy) 1610 + v = *(p2 + 1); 1611 + else 1612 + u = *(p2 + 1); 1613 + } 1614 + 1615 + s32 = ay[(int)y] + rv[(int)v]; 1616 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 1617 + 0 : (__u8)s32); 1618 + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; 1619 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 1620 + 0 : (__u8)s32); 1621 + s32 = ay[(int)y] + bu[(int)u]; 1622 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 1623 + 0 : (__u8)s32); 1624 + 1625 + if ((true == last) && rump) { 1626 + pcache = &cache[0]; 1627 + switch (bytesperpixel - rump) { 1628 + case 1: { 1629 + *p3 = r; 1630 + *pcache++ = g; 1631 + *pcache++ = b; 1632 + break; 1633 + } 1634 + case 2: { 1635 + *p3 = r; 1636 + *(p3 + 1) = g; 1637 + *pcache++ = b; 1638 + break; 1639 + } 1640 + default: { 1641 + SAY("MISTAKE: %i=rump\n", \ 1642 + bytesperpixel - rump); 1643 + return -EFAULT; 1644 + } 1645 + } 1646 + } else { 1647 + *p3 = r; 1648 + *(p3 + 1) = g; 1649 + *(p3 + 2) = b; 1650 + } 1651 + p2 += 2; 1652 + if (true == isuy) 1653 + isuy = false; 1654 + else 1655 + isuy = true; 1656 + p3 += bytesperpixel; 1657 + } 1658 + return 0; 1659 + } else { 1660 + /*---------------------------------------------------*/ 1661 + /* 1662 + ** BGR 1663 + */ 1664 + /*---------------------------------------------------*/ 1665 + while (pz > p2) { 1666 + if (pr <= (p3 + bytesperpixel)) 1667 + last = true; 1668 + else 1669 + last = false; 1670 + y = *p2; 1671 + if ((true == last) && (0x0C & mask)) { 1672 + if (0x04 & mask) { 1673 + if (true == isuy) 1674 + v = margin; 1675 + else 1676 + u = margin; 1677 + } 1678 + else 1679 + if (0x08 & mask) 1680 + ; 1681 + } else { 1682 + if (true == isuy) 1683 + v = *(p2 + 1); 1684 + else 1685 + u = *(p2 + 1); 1686 + } 1687 + 1688 + s32 = ay[(int)y] + rv[(int)v]; 1689 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 1690 + 0 : (__u8)s32); 1691 + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; 1692 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 1693 + 0 : (__u8)s32); 1694 + s32 = ay[(int)y] + bu[(int)u]; 1695 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 1696 + 0 : (__u8)s32); 1697 + 1698 + if ((true == last) && rump) { 1699 + pcache = &cache[0]; 1700 + switch (bytesperpixel - rump) { 1701 + case 1: { 1702 + *p3 = b; 1703 + *pcache++ = g; 1704 + *pcache++ = r; 1705 + break; 1706 + } 1707 + case 2: { 1708 + *p3 = b; 1709 + *(p3 + 1) = g; 1710 + *pcache++ = r; 1711 + break; 1712 + } 1713 + default: { 1714 + SAY("MISTAKE: %i=rump\n", \ 1715 + bytesperpixel - rump); 1716 + return -EFAULT; 1717 + } 1718 + } 1719 + } else { 1720 + *p3 = b; 1721 + *(p3 + 1) = g; 1722 + *(p3 + 2) = r; 1723 + } 1724 + p2 += 2; 1725 + if (true == isuy) 1726 + isuy = false; 1727 + else 1728 + isuy = true; 1729 + p3 += bytesperpixel; 1730 + } 1731 + } 1732 + return 0; 1733 + } else { 1734 + if (false == byteswaporder) { 1735 + /*---------------------------------------------------*/ 1736 + /* 1737 + ** RGB DECIMATED 1738 + */ 1739 + /*---------------------------------------------------*/ 1740 + while (pz > p2) { 1741 + if (pr <= (p3 + bytesperpixel)) 1742 + last = true; 1743 + else 1744 + last = false; 1745 + y = *p2; 1746 + if ((true == last) && (0x0C & mask)) { 1747 + if (0x04 & mask) { 1748 + if (true == isuy) 1749 + v = margin; 1750 + else 1751 + u = margin; 1752 + } else 1753 + if (0x08 & mask) 1754 + ; 1755 + } else { 1756 + if (true == isuy) 1757 + v = *(p2 + 1); 1758 + else 1759 + u = *(p2 + 1); 1760 + } 1761 + 1762 + if (true == isuy) { 1763 + s32 = ay[(int)y] + rv[(int)v]; 1764 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 1765 + 0 : (__u8)s32); 1766 + s32 = ay[(int)y] - gu[(int)u] - \ 1767 + gv[(int)v]; 1768 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 1769 + 0 : (__u8)s32); 1770 + s32 = ay[(int)y] + bu[(int)u]; 1771 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 1772 + 0 : (__u8)s32); 1773 + 1774 + if ((true == last) && rump) { 1775 + pcache = &cache[0]; 1776 + switch (bytesperpixel - rump) { 1777 + case 1: { 1778 + *p3 = r; 1779 + *pcache++ = g; 1780 + *pcache++ = b; 1781 + break; 1782 + } 1783 + case 2: { 1784 + *p3 = r; 1785 + *(p3 + 1) = g; 1786 + *pcache++ = b; 1787 + break; 1788 + } 1789 + default: { 1790 + SAY("MISTAKE: " \ 1791 + "%i=rump\n", \ 1792 + bytesperpixel - rump); 1793 + return -EFAULT; 1794 + } 1795 + } 1796 + } else { 1797 + *p3 = r; 1798 + *(p3 + 1) = g; 1799 + *(p3 + 2) = b; 1800 + } 1801 + isuy = false; 1802 + p3 += bytesperpixel; 1803 + } else { 1804 + isuy = true; 1805 + } 1806 + p2 += 2; 1807 + } 1808 + return 0; 1809 + } else { 1810 + /*---------------------------------------------------*/ 1811 + /* 1812 + * BGR DECIMATED 1813 + */ 1814 + /*---------------------------------------------------*/ 1815 + while (pz > p2) { 1816 + if (pr <= (p3 + bytesperpixel)) 1817 + last = true; 1818 + else 1819 + last = false; 1820 + y = *p2; 1821 + if ((true == last) && (0x0C & mask)) { 1822 + if (0x04 & mask) { 1823 + if (true == isuy) 1824 + v = margin; 1825 + else 1826 + u = margin; 1827 + } else 1828 + if (0x08 & mask) 1829 + ; 1830 + } else { 1831 + if (true == isuy) 1832 + v = *(p2 + 1); 1833 + else 1834 + u = *(p2 + 1); 1835 + } 1836 + 1837 + if (true == isuy) { 1838 + 1839 + s32 = ay[(int)y] + rv[(int)v]; 1840 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 1841 + 0 : (__u8)s32); 1842 + s32 = ay[(int)y] - gu[(int)u] - \ 1843 + gv[(int)v]; 1844 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 1845 + 0 : (__u8)s32); 1846 + s32 = ay[(int)y] + bu[(int)u]; 1847 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 1848 + 0 : (__u8)s32); 1849 + 1850 + if ((true == last) && rump) { 1851 + pcache = &cache[0]; 1852 + switch (bytesperpixel - rump) { 1853 + case 1: { 1854 + *p3 = b; 1855 + *pcache++ = g; 1856 + *pcache++ = r; 1857 + break; 1858 + } 1859 + case 2: { 1860 + *p3 = b; 1861 + *(p3 + 1) = g; 1862 + *pcache++ = r; 1863 + break; 1864 + } 1865 + default: { 1866 + SAY("MISTAKE: " \ 1867 + "%i=rump\n", \ 1868 + bytesperpixel - rump); 1869 + return -EFAULT; 1870 + } 1871 + } 1872 + } else { 1873 + *p3 = b; 1874 + *(p3 + 1) = g; 1875 + *(p3 + 2) = r; 1876 + } 1877 + isuy = false; 1878 + p3 += bytesperpixel; 1879 + } 1880 + else 1881 + isuy = true; 1882 + p2 += 2; 1883 + } 1884 + return 0; 1885 + } 1886 + } 1887 + break; 1888 + } 1889 + case 4: 1890 + { 1891 + if (false == decimatepixel) { 1892 + if (false == byteswaporder) { 1893 + /*---------------------------------------------------*/ 1894 + /* 1895 + ** RGBA 1896 + */ 1897 + /*---------------------------------------------------*/ 1898 + while (pz > p2) { 1899 + if (pr <= (p3 + bytesperpixel)) 1900 + last = true; 1901 + else 1902 + last = false; 1903 + y = *p2; 1904 + if ((true == last) && (0x0C & mask)) { 1905 + if (0x04 & mask) { 1906 + if (true == isuy) 1907 + v = margin; 1908 + else 1909 + u = margin; 1910 + } else 1911 + if (0x08 & mask) 1912 + ; 1913 + } else { 1914 + if (true == isuy) 1915 + v = *(p2 + 1); 1916 + else 1917 + u = *(p2 + 1); 1918 + } 1919 + 1920 + s32 = ay[(int)y] + rv[(int)v]; 1921 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 1922 + 0 : (__u8)s32); 1923 + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; 1924 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 1925 + 0 : (__u8)s32); 1926 + s32 = ay[(int)y] + bu[(int)u]; 1927 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 1928 + 0 : (__u8)s32); 1929 + 1930 + if ((true == last) && rump) { 1931 + pcache = &cache[0]; 1932 + switch (bytesperpixel - rump) { 1933 + case 1: { 1934 + *p3 = r; 1935 + *pcache++ = g; 1936 + *pcache++ = b; 1937 + *pcache++ = 0; 1938 + break; 1939 + } 1940 + case 2: { 1941 + *p3 = r; 1942 + *(p3 + 1) = g; 1943 + *pcache++ = b; 1944 + *pcache++ = 0; 1945 + break; 1946 + } 1947 + case 3: { 1948 + *p3 = r; 1949 + *(p3 + 1) = g; 1950 + *(p3 + 2) = b; 1951 + *pcache++ = 0; 1952 + break; 1953 + } 1954 + default: { 1955 + SAY("MISTAKE: %i=rump\n", \ 1956 + bytesperpixel - rump); 1957 + return -EFAULT; 1958 + } 1959 + } 1960 + } else { 1961 + *p3 = r; 1962 + *(p3 + 1) = g; 1963 + *(p3 + 2) = b; 1964 + *(p3 + 3) = 0; 1965 + } 1966 + p2 += 2; 1967 + if (true == isuy) 1968 + isuy = false; 1969 + else 1970 + isuy = true; 1971 + p3 += bytesperpixel; 1972 + } 1973 + return 0; 1974 + } else { 1975 + /*---------------------------------------------------*/ 1976 + /* 1977 + ** BGRA 1978 + */ 1979 + /*---------------------------------------------------*/ 1980 + while (pz > p2) { 1981 + if (pr <= (p3 + bytesperpixel)) 1982 + last = true; 1983 + else 1984 + last = false; 1985 + y = *p2; 1986 + if ((true == last) && (0x0C & mask)) { 1987 + if (0x04 & mask) { 1988 + if (true == isuy) 1989 + v = margin; 1990 + else 1991 + u = margin; 1992 + } else 1993 + if (0x08 & mask) 1994 + ; 1995 + } else { 1996 + if (true == isuy) 1997 + v = *(p2 + 1); 1998 + else 1999 + u = *(p2 + 1); 2000 + } 2001 + 2002 + s32 = ay[(int)y] + rv[(int)v]; 2003 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 2004 + 0 : (__u8)s32); 2005 + s32 = ay[(int)y] - gu[(int)u] - gv[(int)v]; 2006 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 2007 + 0 : (__u8)s32); 2008 + s32 = ay[(int)y] + bu[(int)u]; 2009 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 2010 + 0 : (__u8)s32); 2011 + 2012 + if ((true == last) && rump) { 2013 + pcache = &cache[0]; 2014 + switch (bytesperpixel - rump) { 2015 + case 1: { 2016 + *p3 = b; 2017 + *pcache++ = g; 2018 + *pcache++ = r; 2019 + *pcache++ = 0; 2020 + break; 2021 + } 2022 + case 2: { 2023 + *p3 = b; 2024 + *(p3 + 1) = g; 2025 + *pcache++ = r; 2026 + *pcache++ = 0; 2027 + break; 2028 + } 2029 + case 3: { 2030 + *p3 = b; 2031 + *(p3 + 1) = g; 2032 + *(p3 + 2) = r; 2033 + *pcache++ = 0; 2034 + break; 2035 + } 2036 + default: { 2037 + SAY("MISTAKE: %i=rump\n", \ 2038 + bytesperpixel - rump); 2039 + return -EFAULT; 2040 + } 2041 + } 2042 + } else { 2043 + *p3 = b; 2044 + *(p3 + 1) = g; 2045 + *(p3 + 2) = r; 2046 + *(p3 + 3) = 0; 2047 + } 2048 + p2 += 2; 2049 + if (true == isuy) 2050 + isuy = false; 2051 + else 2052 + isuy = true; 2053 + p3 += bytesperpixel; 2054 + } 2055 + } 2056 + return 0; 2057 + } else { 2058 + if (false == byteswaporder) { 2059 + /*---------------------------------------------------*/ 2060 + /* 2061 + ** RGBA DECIMATED 2062 + */ 2063 + /*---------------------------------------------------*/ 2064 + while (pz > p2) { 2065 + if (pr <= (p3 + bytesperpixel)) 2066 + last = true; 2067 + else 2068 + last = false; 2069 + y = *p2; 2070 + if ((true == last) && (0x0C & mask)) { 2071 + if (0x04 & mask) { 2072 + if (true == isuy) 2073 + v = margin; 2074 + else 2075 + u = margin; 2076 + } else 2077 + if (0x08 & mask) 2078 + ; 2079 + } else { 2080 + if (true == isuy) 2081 + v = *(p2 + 1); 2082 + else 2083 + u = *(p2 + 1); 2084 + } 2085 + 2086 + if (true == isuy) { 2087 + 2088 + s32 = ay[(int)y] + rv[(int)v]; 2089 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 2090 + 0 : (__u8)s32); 2091 + s32 = ay[(int)y] - gu[(int)u] - \ 2092 + gv[(int)v]; 2093 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 2094 + 0 : (__u8)s32); 2095 + s32 = ay[(int)y] + bu[(int)u]; 2096 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 2097 + 0 : (__u8)s32); 2098 + 2099 + if ((true == last) && rump) { 2100 + pcache = &cache[0]; 2101 + switch (bytesperpixel - rump) { 2102 + case 1: { 2103 + *p3 = r; 2104 + *pcache++ = g; 2105 + *pcache++ = b; 2106 + *pcache++ = 0; 2107 + break; 2108 + } 2109 + case 2: { 2110 + *p3 = r; 2111 + *(p3 + 1) = g; 2112 + *pcache++ = b; 2113 + *pcache++ = 0; 2114 + break; 2115 + } 2116 + case 3: { 2117 + *p3 = r; 2118 + *(p3 + 1) = g; 2119 + *(p3 + 2) = b; 2120 + *pcache++ = 0; 2121 + break; 2122 + } 2123 + default: { 2124 + SAY("MISTAKE: " \ 2125 + "%i=rump\n", \ 2126 + bytesperpixel - \ 2127 + rump); 2128 + return -EFAULT; 2129 + } 2130 + } 2131 + } else { 2132 + *p3 = r; 2133 + *(p3 + 1) = g; 2134 + *(p3 + 2) = b; 2135 + *(p3 + 3) = 0; 2136 + } 2137 + isuy = false; 2138 + p3 += bytesperpixel; 2139 + } else 2140 + isuy = true; 2141 + p2 += 2; 2142 + } 2143 + return 0; 2144 + } else { 2145 + /*---------------------------------------------------*/ 2146 + /* 2147 + ** BGRA DECIMATED 2148 + */ 2149 + /*---------------------------------------------------*/ 2150 + while (pz > p2) { 2151 + if (pr <= (p3 + bytesperpixel)) 2152 + last = true; 2153 + else 2154 + last = false; 2155 + y = *p2; 2156 + if ((true == last) && (0x0C & mask)) { 2157 + if (0x04 & mask) { 2158 + if (true == isuy) 2159 + v = margin; 2160 + else 2161 + u = margin; 2162 + } else 2163 + if (0x08 & mask) 2164 + ; 2165 + } else { 2166 + if (true == isuy) 2167 + v = *(p2 + 1); 2168 + else 2169 + u = *(p2 + 1); 2170 + } 2171 + 2172 + if (true == isuy) { 2173 + s32 = ay[(int)y] + rv[(int)v]; 2174 + r = (255 < s32) ? 255 : ((0 > s32) ? \ 2175 + 0 : (__u8)s32); 2176 + s32 = ay[(int)y] - gu[(int)u] - \ 2177 + gv[(int)v]; 2178 + g = (255 < s32) ? 255 : ((0 > s32) ? \ 2179 + 0 : (__u8)s32); 2180 + s32 = ay[(int)y] + bu[(int)u]; 2181 + b = (255 < s32) ? 255 : ((0 > s32) ? \ 2182 + 0 : (__u8)s32); 2183 + 2184 + if ((true == last) && rump) { 2185 + pcache = &cache[0]; 2186 + switch (bytesperpixel - rump) { 2187 + case 1: { 2188 + *p3 = b; 2189 + *pcache++ = g; 2190 + *pcache++ = r; 2191 + *pcache++ = 0; 2192 + break; 2193 + } 2194 + case 2: { 2195 + *p3 = b; 2196 + *(p3 + 1) = g; 2197 + *pcache++ = r; 2198 + *pcache++ = 0; 2199 + break; 2200 + } 2201 + case 3: { 2202 + *p3 = b; 2203 + *(p3 + 1) = g; 2204 + *(p3 + 2) = r; 2205 + *pcache++ = 0; 2206 + break; 2207 + } 2208 + default: { 2209 + SAY("MISTAKE: " \ 2210 + "%i=rump\n", \ 2211 + bytesperpixel - rump); 2212 + return -EFAULT; 2213 + } 2214 + } 2215 + } else { 2216 + *p3 = b; 2217 + *(p3 + 1) = g; 2218 + *(p3 + 2) = r; 2219 + *(p3 + 3) = 0; 2220 + } 2221 + isuy = false; 2222 + p3 += bytesperpixel; 2223 + } else 2224 + isuy = true; 2225 + p2 += 2; 2226 + } 2227 + return 0; 2228 + } 2229 + } 2230 + break; 2231 + } 2232 + default: { 2233 + SAY("MISTAKE: %i=bytesperpixel\n", bytesperpixel); 2234 + return -EFAULT; 2235 + } 2236 + } 2237 + return 0; 2238 + } 2239 + /*****************************************************************************/ 2240 + void 2241 + debrief(struct easycap *peasycap) 2242 + { 2243 + if ((struct usb_device *)NULL != peasycap->pusb_device) { 2244 + check_stk(peasycap->pusb_device); 2245 + check_saa(peasycap->pusb_device); 2246 + sayreadonly(peasycap); 2247 + SAY("%i=peasycap->field_fill\n", peasycap->field_fill); 2248 + SAY("%i=peasycap->field_read\n", peasycap->field_read); 2249 + SAY("%i=peasycap->frame_fill\n", peasycap->frame_fill); 2250 + SAY("%i=peasycap->frame_read\n", peasycap->frame_read); 2251 + } 2252 + return; 2253 + } 2254 + /*****************************************************************************/ 2255 + void 2256 + sayreadonly(struct easycap *peasycap) 2257 + { 2258 + static int done; 2259 + int got00, got1F, got60, got61, got62; 2260 + 2261 + if ((!done) && ((struct usb_device *)NULL != peasycap->pusb_device)) { 2262 + done = 1; 2263 + got00 = read_saa(peasycap->pusb_device, 0x00); 2264 + got1F = read_saa(peasycap->pusb_device, 0x1F); 2265 + got60 = read_saa(peasycap->pusb_device, 0x60); 2266 + got61 = read_saa(peasycap->pusb_device, 0x61); 2267 + got62 = read_saa(peasycap->pusb_device, 0x62); 2268 + SAY("0x%02X=reg0x00 0x%02X=reg0x1F\n", got00, got1F); 2269 + SAY("0x%02X=reg0x60 0x%02X=reg0x61 0x%02X=reg0x62\n", \ 2270 + got60, got61, got62); 2271 + } 2272 + return; 2273 + } 2274 + /*****************************************************************************/ 2275 + /*---------------------------------------------------------------------------*/ 2276 + /* 2277 + * SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434 2278 + */ 2279 + /*---------------------------------------------------------------------------*/ 2280 + int easycap_mmap(struct file *file, struct vm_area_struct *pvma) 2281 + { 2282 + 2283 + JOT(8, "\n"); 2284 + 2285 + pvma->vm_ops = &easycap_vm_ops; 2286 + pvma->vm_flags |= VM_RESERVED; 2287 + if (NULL != file) 2288 + pvma->vm_private_data = file->private_data; 2289 + easycap_vma_open(pvma); 2290 + return 0; 2291 + } 2292 + /*****************************************************************************/ 2293 + void 2294 + easycap_vma_open(struct vm_area_struct *pvma) 2295 + { 2296 + struct easycap *peasycap; 2297 + 2298 + peasycap = pvma->vm_private_data; 2299 + if (NULL != peasycap) 2300 + peasycap->vma_many++; 2301 + 2302 + JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); 2303 + 2304 + return; 2305 + } 2306 + /*****************************************************************************/ 2307 + void 2308 + easycap_vma_close(struct vm_area_struct *pvma) 2309 + { 2310 + struct easycap *peasycap; 2311 + 2312 + peasycap = pvma->vm_private_data; 2313 + if (NULL != peasycap) { 2314 + peasycap->vma_many--; 2315 + JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many); 2316 + } 2317 + return; 2318 + } 2319 + /*****************************************************************************/ 2320 + int 2321 + easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf) 2322 + { 2323 + int k, m, retcode; 2324 + void *pbuf; 2325 + struct page *page; 2326 + struct easycap *peasycap; 2327 + 2328 + retcode = VM_FAULT_NOPAGE; 2329 + pbuf = (void *)NULL; 2330 + page = (struct page *)NULL; 2331 + 2332 + if (NULL == pvma) { 2333 + SAY("pvma is NULL\n"); 2334 + return retcode; 2335 + } 2336 + if (NULL == pvmf) { 2337 + SAY("pvmf is NULL\n"); 2338 + return retcode; 2339 + } 2340 + 2341 + k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE); 2342 + m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE); 2343 + 2344 + if (!m) 2345 + JOT(4, "%4i=k, %4i=m\n", k, m); 2346 + else 2347 + JOT(16, "%4i=k, %4i=m\n", k, m); 2348 + 2349 + if ((0 > k) || (FRAME_BUFFER_MANY <= k)) { 2350 + SAY("ERROR: buffer index %i out of range\n", k); 2351 + return retcode; 2352 + } 2353 + if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) { 2354 + SAY("ERROR: page number %i out of range\n", m); 2355 + return retcode; 2356 + } 2357 + peasycap = pvma->vm_private_data; 2358 + if (NULL == peasycap) { 2359 + SAY("ERROR: peasycap is NULL\n"); 2360 + return retcode; 2361 + } 2362 + mutex_lock(&(peasycap->mutex_mmap_video[0])); 2363 + /*---------------------------------------------------------------------------*/ 2364 + pbuf = peasycap->frame_buffer[k][m].pgo; 2365 + if (NULL == pbuf) { 2366 + SAY("ERROR: pbuf is NULL\n"); 2367 + goto finish; 2368 + } 2369 + page = virt_to_page(pbuf); 2370 + if (NULL == page) { 2371 + SAY("ERROR: page is NULL\n"); 2372 + goto finish; 2373 + } 2374 + get_page(page); 2375 + /*---------------------------------------------------------------------------*/ 2376 + finish: 2377 + mutex_unlock(&(peasycap->mutex_mmap_video[0])); 2378 + if (NULL == page) { 2379 + SAY("ERROR: page is NULL after get_page(page)\n"); 2380 + } else { 2381 + pvmf->page = page; 2382 + retcode = VM_FAULT_MINOR; 2383 + } 2384 + return retcode; 2385 + } 2386 + /*****************************************************************************/ 2387 + /*---------------------------------------------------------------------------*/ 2388 + /* 2389 + * ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS 2390 + * PROVIDED peasycap->video_idle IS ZER0. REGARDLESS OF THIS BEING TRUE, 2391 + * IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO. 2392 + * 2393 + * THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP. 2394 + * 2395 + * INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE 2396 + * STORED IN THE TWO-BYTE STATUS PARAMETER 2397 + * peasycap->field_buffer[peasycap->field_fill][0].kount 2398 + * NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER. 2399 + * 2400 + * THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H 2401 + * CHIP. 2402 + * 2403 + * THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE: 2404 + * 0 != (kount & 0x8000) => AT LEAST ONE URB COMPLETED WITH ERRORS 2405 + * 0 != (kount & 0x4000) => BUFFER HAS TOO MUCH DATA 2406 + * 0 != (kount & 0x2000) => BUFFER HAS NOT ENOUGH DATA 2407 + * 0 != (kount & 0x0400) => FIELD WAS SUBMITTED BY BRIDGER ROUTINE 2408 + * 0 != (kount & 0x0200) => FIELD BUFFER NOT YET CHECKED 2409 + * 0 != (kount & 0x0100) => BUFFER HAS TWO EXTRA BYTES - WHY? 2410 + */ 2411 + /*---------------------------------------------------------------------------*/ 2412 + void 2413 + easycap_complete(struct urb *purb) 2414 + { 2415 + static int mt; 2416 + struct easycap *peasycap; 2417 + struct data_buffer *pfield_buffer; 2418 + char errbuf[16]; 2419 + int i, more, much, leap, rc, last; 2420 + int videofieldamount; 2421 + unsigned int override; 2422 + int framestatus, framelength, frameactual, frameoffset; 2423 + __u8 *pu; 2424 + #if defined(BRIDGER) 2425 + struct timeval timeval; 2426 + long long usec; 2427 + #endif /*BRIDGER*/ 2428 + 2429 + if (NULL == purb) { 2430 + SAY("ERROR: easycap_complete(): purb is NULL\n"); 2431 + return; 2432 + } 2433 + peasycap = purb->context; 2434 + if (NULL == peasycap) { 2435 + SAY("ERROR: easycap_complete(): peasycap is NULL\n"); 2436 + return; 2437 + } 2438 + 2439 + if (peasycap->video_eof) 2440 + return; 2441 + 2442 + for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) 2443 + if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo) 2444 + break; 2445 + JOT(16, "%2i=urb\n", i); 2446 + last = peasycap->video_isoc_sequence; 2447 + if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && \ 2448 + (0 != i)) || \ 2449 + (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && \ 2450 + ((last + 1) != i))) { 2451 + SAY("ERROR: out-of-order urbs %i,%i ... continuing\n", last, i); 2452 + } 2453 + peasycap->video_isoc_sequence = i; 2454 + 2455 + if (peasycap->video_idle) { 2456 + JOT(16, "%i=video_idle %i=video_isoc_streaming\n", \ 2457 + peasycap->video_idle, peasycap->video_isoc_streaming); 2458 + if (peasycap->video_isoc_streaming) { 2459 + rc = usb_submit_urb(purb, GFP_ATOMIC); 2460 + if (0 != rc) { 2461 + SAY("ERROR: while %i=video_idle, " \ 2462 + "usb_submit_urb() failed with rc:\n", \ 2463 + peasycap->video_idle); 2464 + switch (rc) { 2465 + case -ENOMEM: { 2466 + SAY("ENOMEM\n"); 2467 + break; 2468 + } 2469 + case -ENODEV: { 2470 + SAY("ENODEV\n"); 2471 + break; 2472 + } 2473 + case -ENXIO: { 2474 + SAY("ENXIO\n"); 2475 + break; 2476 + } 2477 + case -EINVAL: { 2478 + SAY("EINVAL\n"); 2479 + break; 2480 + } 2481 + case -EAGAIN: { 2482 + SAY("EAGAIN\n"); 2483 + break; 2484 + } 2485 + case -EFBIG: { 2486 + SAY("EFBIG\n"); 2487 + break; 2488 + } 2489 + case -EPIPE: { 2490 + SAY("EPIPE\n"); 2491 + break; 2492 + } 2493 + case -EMSGSIZE: { 2494 + SAY("EMSGSIZE\n"); 2495 + break; 2496 + } 2497 + default: { 2498 + SAY("0x%08X\n", rc); 2499 + break; 2500 + } 2501 + } 2502 + } 2503 + } 2504 + return; 2505 + } 2506 + override = 0; 2507 + /*---------------------------------------------------------------------------*/ 2508 + if (FIELD_BUFFER_MANY <= peasycap->field_fill) { 2509 + SAY("ERROR: bad peasycap->field_fill\n"); 2510 + return; 2511 + } 2512 + if (purb->status) { 2513 + if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) { 2514 + JOT(8, "urb status -ESHUTDOWN or -ENOENT\n"); 2515 + return; 2516 + } 2517 + 2518 + (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ; 2519 + SAY("ERROR: bad urb status:\n"); 2520 + switch (purb->status) { 2521 + case -EINPROGRESS: { 2522 + SAY("-EINPROGRESS\n"); break; 2523 + } 2524 + case -ENOSR: { 2525 + SAY("-ENOSR\n"); break; 2526 + } 2527 + case -EPIPE: { 2528 + SAY("-EPIPE\n"); break; 2529 + } 2530 + case -EOVERFLOW: { 2531 + SAY("-EOVERFLOW\n"); break; 2532 + } 2533 + case -EPROTO: { 2534 + SAY("-EPROTO\n"); break; 2535 + } 2536 + case -EILSEQ: { 2537 + SAY("-EILSEQ\n"); break; 2538 + } 2539 + case -ETIMEDOUT: { 2540 + SAY("-ETIMEDOUT\n"); break; 2541 + } 2542 + case -EMSGSIZE: { 2543 + SAY("-EMSGSIZE\n"); break; 2544 + } 2545 + case -EOPNOTSUPP: { 2546 + SAY("-EOPNOTSUPP\n"); break; 2547 + } 2548 + case -EPFNOSUPPORT: { 2549 + SAY("-EPFNOSUPPORT\n"); break; 2550 + } 2551 + case -EAFNOSUPPORT: { 2552 + SAY("-EAFNOSUPPORT\n"); break; 2553 + } 2554 + case -EADDRINUSE: { 2555 + SAY("-EADDRINUSE\n"); break; 2556 + } 2557 + case -EADDRNOTAVAIL: { 2558 + SAY("-EADDRNOTAVAIL\n"); break; 2559 + } 2560 + case -ENOBUFS: { 2561 + SAY("-ENOBUFS\n"); break; 2562 + } 2563 + case -EISCONN: { 2564 + SAY("-EISCONN\n"); break; 2565 + } 2566 + case -ENOTCONN: { 2567 + SAY("-ENOTCONN\n"); break; 2568 + } 2569 + case -ESHUTDOWN: { 2570 + SAY("-ESHUTDOWN\n"); break; 2571 + } 2572 + case -ENOENT: { 2573 + SAY("-ENOENT\n"); break; 2574 + } 2575 + case -ECONNRESET: { 2576 + SAY("-ECONNRESET\n"); break; 2577 + } 2578 + default: { 2579 + SAY("unknown error code 0x%08X\n", purb->status); break; 2580 + } 2581 + } 2582 + /*---------------------------------------------------------------------------*/ 2583 + } else { 2584 + for (i = 0; i < purb->number_of_packets; i++) { 2585 + if (0 != purb->iso_frame_desc[i].status) { 2586 + (peasycap->field_buffer\ 2587 + [peasycap->field_fill][0].kount) |= 0x8000 ; 2588 + switch (purb->iso_frame_desc[i].status) { 2589 + case 0: { 2590 + strcpy(&errbuf[0], "OK"); break; 2591 + } 2592 + case -ENOENT: { 2593 + strcpy(&errbuf[0], "-ENOENT"); break; 2594 + } 2595 + case -EINPROGRESS: { 2596 + strcpy(&errbuf[0], "-EINPROGRESS"); break; 2597 + } 2598 + case -EPROTO: { 2599 + strcpy(&errbuf[0], "-EPROTO"); break; 2600 + } 2601 + case -EILSEQ: { 2602 + strcpy(&errbuf[0], "-EILSEQ"); break; 2603 + } 2604 + case -ETIME: { 2605 + strcpy(&errbuf[0], "-ETIME"); break; 2606 + } 2607 + case -ETIMEDOUT: { 2608 + strcpy(&errbuf[0], "-ETIMEDOUT"); break; 2609 + } 2610 + case -EPIPE: { 2611 + strcpy(&errbuf[0], "-EPIPE"); break; 2612 + } 2613 + case -ECOMM: { 2614 + strcpy(&errbuf[0], "-ECOMM"); break; 2615 + } 2616 + case -ENOSR: { 2617 + strcpy(&errbuf[0], "-ENOSR"); break; 2618 + } 2619 + case -EOVERFLOW: { 2620 + strcpy(&errbuf[0], "-EOVERFLOW"); break; 2621 + } 2622 + case -EREMOTEIO: { 2623 + strcpy(&errbuf[0], "-EREMOTEIO"); break; 2624 + } 2625 + case -ENODEV: { 2626 + strcpy(&errbuf[0], "-ENODEV"); break; 2627 + } 2628 + case -EXDEV: { 2629 + strcpy(&errbuf[0], "-EXDEV"); break; 2630 + } 2631 + case -EINVAL: { 2632 + strcpy(&errbuf[0], "-EINVAL"); break; 2633 + } 2634 + case -ECONNRESET: { 2635 + strcpy(&errbuf[0], "-ECONNRESET"); break; 2636 + } 2637 + case -ESHUTDOWN: { 2638 + strcpy(&errbuf[0], "-ESHUTDOWN"); break; 2639 + } 2640 + default: { 2641 + strcpy(&errbuf[0], "unknown error"); break; 2642 + } 2643 + } 2644 + } 2645 + framestatus = purb->iso_frame_desc[i].status; 2646 + framelength = purb->iso_frame_desc[i].length; 2647 + frameactual = purb->iso_frame_desc[i].actual_length; 2648 + frameoffset = purb->iso_frame_desc[i].offset; 2649 + 2650 + JOT(16, "frame[%2i]:" \ 2651 + "%4i=status " \ 2652 + "%4i=actual " \ 2653 + "%4i=length " \ 2654 + "%5i=offset\n", \ 2655 + i, framestatus, frameactual, framelength, frameoffset); 2656 + if (!purb->iso_frame_desc[i].status) { 2657 + more = purb->iso_frame_desc[i].actual_length; 2658 + pfield_buffer = &peasycap->field_buffer\ 2659 + [peasycap->field_fill][peasycap->field_page]; 2660 + videofieldamount = (peasycap->field_page * \ 2661 + PAGE_SIZE) + \ 2662 + (int)(pfield_buffer->pto - pfield_buffer->pgo); 2663 + if (4 == more) 2664 + mt++; 2665 + if (4 < more) { 2666 + if (mt) { 2667 + JOT(8, "%4i empty video urb frames\n", mt); 2668 + mt = 0; 2669 + } 2670 + if (FIELD_BUFFER_MANY <= peasycap->field_fill) { 2671 + SAY("ERROR: bad peasycap->field_fill\n"); 2672 + return; 2673 + } 2674 + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ 2675 + peasycap->field_page) { 2676 + SAY("ERROR: bad peasycap->field_page\n"); 2677 + return; 2678 + } 2679 + pfield_buffer = &peasycap->field_buffer\ 2680 + [peasycap->field_fill][peasycap->field_page]; 2681 + pu = (__u8 *)(purb->transfer_buffer + \ 2682 + purb->iso_frame_desc[i].offset); 2683 + if (0x80 & *pu) 2684 + leap = 8; 2685 + else 2686 + leap = 4; 2687 + /*--------------------------------------------------------------------------*/ 2688 + /* 2689 + * EIGHT-BYTE END-OF-VIDEOFIELD MARKER. 2690 + * NOTE: A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY, 2691 + * CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD. 2692 + * 2693 + * PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER 2694 + * BYTE OF 2695 + * peasycap->field_buffer[peasycap->field_fill][0].kount 2696 + * THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS 2697 + * UPDATED AND field_fill IS BUMPED. IF THE FIELD BUFFER CONTAINS BAD DATA 2698 + * NOTHING IS OFFERED TO dqbuf(). 2699 + * 2700 + * THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT 2701 + * RESTS WITH dqbuf(). 2702 + */ 2703 + /*---------------------------------------------------------------------------*/ 2704 + if ((8 == more) || override) { 2705 + if (videofieldamount > \ 2706 + peasycap->videofieldamount) { 2707 + if (2 == videofieldamount - \ 2708 + peasycap->\ 2709 + videofieldamount) 2710 + (peasycap->field_buffer\ 2711 + [peasycap->field_fill]\ 2712 + [0].kount) |= 0x0100; 2713 + else 2714 + (peasycap->field_buffer\ 2715 + [peasycap->field_fill]\ 2716 + [0].kount) |= 0x4000; 2717 + } else if (videofieldamount < \ 2718 + peasycap->\ 2719 + videofieldamount) { 2720 + (peasycap->field_buffer\ 2721 + [peasycap->field_fill]\ 2722 + [0].kount) |= 0x2000; 2723 + } 2724 + if (!(0xFF00 & peasycap->field_buffer\ 2725 + [peasycap->field_fill]\ 2726 + [0].kount)) { 2727 + (peasycap->video_junk)--; 2728 + if (-16 > peasycap->video_junk) 2729 + peasycap->video_junk = -16; 2730 + peasycap->field_read = \ 2731 + (peasycap->\ 2732 + field_fill)++; 2733 + 2734 + if (FIELD_BUFFER_MANY <= \ 2735 + peasycap->field_fill) 2736 + peasycap->field_fill = 0; 2737 + peasycap->field_page = 0; 2738 + pfield_buffer = &peasycap->\ 2739 + field_buffer\ 2740 + [peasycap->field_fill]\ 2741 + [peasycap->field_page]; 2742 + pfield_buffer->pto = \ 2743 + pfield_buffer->pgo; 2744 + 2745 + JOT(8, "bumped to: %i=peasycap->" \ 2746 + "field_fill %i=parity\n", \ 2747 + peasycap->field_fill, \ 2748 + 0x00FF & pfield_buffer->kount); 2749 + JOT(8, "field buffer %i has %i " \ 2750 + "bytes fit to be read\n", \ 2751 + peasycap->field_read, \ 2752 + videofieldamount); 2753 + JOT(8, "wakeup call to wq_video, " \ 2754 + "%i=field_read %i=field_fill "\ 2755 + "%i=parity\n", \ 2756 + peasycap->field_read, \ 2757 + peasycap->field_fill, \ 2758 + 0x00FF & peasycap->\ 2759 + field_buffer[peasycap->\ 2760 + field_read][0].kount); 2761 + wake_up_interruptible(&(peasycap->\ 2762 + wq_video)); 2763 + do_gettimeofday(&peasycap->timeval7); 2764 + } else { 2765 + peasycap->video_junk++; 2766 + JOT(8, "field buffer %i had %i " \ 2767 + "bytes, now discarded\n", \ 2768 + peasycap->field_fill, \ 2769 + videofieldamount); 2770 + 2771 + (peasycap->field_fill)++; 2772 + 2773 + if (FIELD_BUFFER_MANY <= \ 2774 + peasycap->field_fill) 2775 + peasycap->field_fill = 0; 2776 + peasycap->field_page = 0; 2777 + pfield_buffer = \ 2778 + &peasycap->field_buffer\ 2779 + [peasycap->field_fill]\ 2780 + [peasycap->field_page]; 2781 + pfield_buffer->pto = \ 2782 + pfield_buffer->pgo; 2783 + 2784 + JOT(8, "bumped to: %i=peasycap->" \ 2785 + "field_fill %i=parity\n", \ 2786 + peasycap->field_fill, \ 2787 + 0x00FF & pfield_buffer->kount); 2788 + } 2789 + if (8 == more) { 2790 + JOT(8, "end-of-field: received " \ 2791 + "parity byte 0x%02X\n", \ 2792 + (0xFF & *pu)); 2793 + if (0x40 & *pu) 2794 + pfield_buffer->kount = 0x0000; 2795 + else 2796 + pfield_buffer->kount = 0x0001; 2797 + JOT(8, "end-of-field: 0x%02X=kount\n",\ 2798 + 0xFF & pfield_buffer->kount); 2799 + } 2800 + } 2801 + /*---------------------------------------------------------------------------*/ 2802 + /* 2803 + * COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER 2804 + */ 2805 + /*---------------------------------------------------------------------------*/ 2806 + pu += leap; 2807 + more -= leap; 2808 + 2809 + if (FIELD_BUFFER_MANY <= peasycap->field_fill) { 2810 + SAY("ERROR: bad peasycap->field_fill\n"); 2811 + return; 2812 + } 2813 + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ 2814 + peasycap->field_page) { 2815 + SAY("ERROR: bad peasycap->field_page\n"); 2816 + return; 2817 + } 2818 + pfield_buffer = &peasycap->field_buffer\ 2819 + [peasycap->field_fill][peasycap->field_page]; 2820 + while (more) { 2821 + pfield_buffer = &peasycap->field_buffer\ 2822 + [peasycap->field_fill]\ 2823 + [peasycap->field_page]; 2824 + if (PAGE_SIZE < (pfield_buffer->pto - \ 2825 + pfield_buffer->pgo)) { 2826 + SAY("ERROR: bad pfield_buffer->pto\n"); 2827 + return; 2828 + } 2829 + if (PAGE_SIZE == (pfield_buffer->pto - \ 2830 + pfield_buffer->pgo)) { 2831 + (peasycap->field_page)++; 2832 + if (FIELD_BUFFER_SIZE/PAGE_SIZE <= \ 2833 + peasycap->field_page) { 2834 + JOT(16, "wrapping peasycap->" \ 2835 + "field_page\n"); 2836 + peasycap->field_page = 0; 2837 + } 2838 + pfield_buffer = &peasycap->\ 2839 + field_buffer\ 2840 + [peasycap->field_fill]\ 2841 + [peasycap->field_page]; 2842 + pfield_buffer->pto = \ 2843 + pfield_buffer->pgo; 2844 + } 2845 + 2846 + much = PAGE_SIZE - (int)(pfield_buffer->pto - \ 2847 + pfield_buffer->pgo); 2848 + 2849 + if (much > more) 2850 + much = more; 2851 + memcpy(pfield_buffer->pto, pu, much); 2852 + pu += much; 2853 + (pfield_buffer->pto) += much; 2854 + more -= much; 2855 + } 2856 + } 2857 + } 2858 + } 2859 + } 2860 + /*---------------------------------------------------------------------------*/ 2861 + /* 2862 + * 2863 + * 2864 + * *** UNDER DEVELOPMENT/TESTING - NOT READY YET! *** 2865 + * 2866 + * 2867 + * 2868 + * VIDEOTAPES MAY HAVE BEEN MANUALLY PAUSED AND RESTARTED DURING RECORDING. 2869 + * THIS CAUSES LOSS OF SYNC, CONFUSING DOWNSTREAM USERSPACE PROGRAMS WHICH 2870 + * MAY INTERPRET THE INTERRUPTION AS A SYMPTOM OF LATENCY. TO OVERCOME THIS 2871 + * THE DRIVER BRIDGES THE HIATUS BY SENDING DUMMY VIDEO FRAMES AT ROUGHLY 2872 + * THE RIGHT TIME INTERVALS IN THE HOPE OF PERSUADING THE DOWNSTREAM USERSPACE 2873 + * PROGRAM TO RESUME NORMAL SERVICE WHEN THE INTERRUPTION IS OVER. 2874 + */ 2875 + /*---------------------------------------------------------------------------*/ 2876 + #if defined(BRIDGER) 2877 + do_gettimeofday(&timeval); 2878 + if (peasycap->timeval7.tv_sec) { 2879 + usec = 1000000*(timeval.tv_sec - peasycap->timeval7.tv_sec) + \ 2880 + (timeval.tv_usec - peasycap->timeval7.tv_usec); 2881 + if (usec > (peasycap->usec + peasycap->tolerate)) { 2882 + JOT(8, "bridging hiatus\n"); 2883 + peasycap->video_junk = 0; 2884 + peasycap->field_buffer[peasycap->field_fill][0].kount |= 0x0400; 2885 + 2886 + peasycap->field_read = (peasycap->field_fill)++; 2887 + 2888 + if (FIELD_BUFFER_MANY <= peasycap->field_fill) \ 2889 + peasycap->field_fill = 0; 2890 + peasycap->field_page = 0; 2891 + pfield_buffer = &peasycap->field_buffer\ 2892 + [peasycap->field_fill][peasycap->field_page]; 2893 + pfield_buffer->pto = pfield_buffer->pgo; 2894 + 2895 + JOT(8, "bumped to: %i=peasycap->field_fill %i=parity\n", \ 2896 + peasycap->field_fill, 0x00FF & pfield_buffer->kount); 2897 + JOT(8, "field buffer %i has %i bytes to be overwritten\n", \ 2898 + peasycap->field_read, videofieldamount); 2899 + JOT(8, "wakeup call to wq_video, " \ 2900 + "%i=field_read %i=field_fill %i=parity\n", \ 2901 + peasycap->field_read, peasycap->field_fill, \ 2902 + 0x00FF & \ 2903 + peasycap->field_buffer[peasycap->field_read][0].kount); 2904 + wake_up_interruptible(&(peasycap->wq_video)); 2905 + do_gettimeofday(&peasycap->timeval7); 2906 + } 2907 + } 2908 + #endif /*BRIDGER*/ 2909 + /*---------------------------------------------------------------------------*/ 2910 + /* 2911 + * RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS. 2912 + * 2913 + * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION 2914 + * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE. 2915 + */ 2916 + /*---------------------------------------------------------------------------*/ 2917 + if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) { 2918 + SAY("easycap driver shutting down on condition green\n"); 2919 + peasycap->video_eof = 1; 2920 + peasycap->audio_eof = 1; 2921 + peasycap->video_junk = -VIDEO_ISOC_BUFFER_MANY; 2922 + wake_up_interruptible(&(peasycap->wq_video)); 2923 + wake_up_interruptible(&(peasycap->wq_audio)); 2924 + return; 2925 + } 2926 + if (peasycap->video_isoc_streaming) { 2927 + rc = usb_submit_urb(purb, GFP_ATOMIC); 2928 + if (0 != rc) { 2929 + SAY("ERROR: while %i=video_idle, usb_submit_urb() failed " \ 2930 + "with rc:\n", peasycap->video_idle); 2931 + switch (rc) { 2932 + case -ENOMEM: { 2933 + SAY("ENOMEM\n"); break; 2934 + } 2935 + case -ENODEV: { 2936 + SAY("ENODEV\n"); break; 2937 + } 2938 + case -ENXIO: { 2939 + SAY("ENXIO\n"); break; 2940 + } 2941 + case -EINVAL: { 2942 + SAY("EINVAL\n"); break; 2943 + } 2944 + case -EAGAIN: { 2945 + SAY("EAGAIN\n"); break; 2946 + } 2947 + case -EFBIG: { 2948 + SAY("EFBIG\n"); break; 2949 + } 2950 + case -EPIPE: { 2951 + SAY("EPIPE\n"); break; 2952 + } 2953 + case -EMSGSIZE: { 2954 + SAY("EMSGSIZE\n"); break; 2955 + } 2956 + default: { 2957 + SAY("0x%08X\n", rc); break; 2958 + } 2959 + } 2960 + } 2961 + } 2962 + return; 2963 + } 2964 + /*****************************************************************************/ 2965 + /*---------------------------------------------------------------------------*/ 2966 + /* 2967 + * 2968 + * FIXME 2969 + * 2970 + * 2971 + * THIS FUNCTION ASSUMES THAT, ON EACH AND EVERY OCCASION THAT THE DEVICE IS 2972 + * PHYSICALLY PLUGGED IN, INTERFACE 0 IS PROBED FIRST. 2973 + * IF THIS IS NOT TRUE, THERE IS THE POSSIBILITY OF AN Oops. 2974 + * 2975 + * THIS HAS NEVER BEEN A PROBLEM IN PRACTICE, BUT SOMETHING SEEMS WRONG HERE. 2976 + */ 2977 + /*---------------------------------------------------------------------------*/ 2978 + int 2979 + easycap_usb_probe(struct usb_interface *pusb_interface, \ 2980 + const struct usb_device_id *id) 2981 + { 2982 + struct usb_device *pusb_device, *pusb_device1; 2983 + struct usb_host_interface *pusb_host_interface; 2984 + struct usb_endpoint_descriptor *pepd; 2985 + struct usb_interface_descriptor *pusb_interface_descriptor; 2986 + struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor; 2987 + struct urb *purb; 2988 + static struct easycap *peasycap /*=NULL*/; 2989 + struct data_urb *pdata_urb; 2990 + size_t wMaxPacketSize; 2991 + int ISOCwMaxPacketSize; 2992 + int BULKwMaxPacketSize; 2993 + int INTwMaxPacketSize; 2994 + int CTRLwMaxPacketSize; 2995 + __u8 bEndpointAddress; 2996 + __u8 ISOCbEndpointAddress; 2997 + __u8 INTbEndpointAddress; 2998 + int isin, i, j, k, m; 2999 + __u8 bInterfaceNumber; 3000 + __u8 bInterfaceClass; 3001 + __u8 bInterfaceSubClass; 3002 + void *pbuf; 3003 + int okalt[8], isokalt; 3004 + int okepn[8], isokepn; 3005 + int okmps[8], isokmps; 3006 + int maxpacketsize; 3007 + int rc; 3008 + 3009 + JOT(4, "\n"); 3010 + 3011 + if ((struct usb_interface *)NULL == pusb_interface) { 3012 + SAY("ERROR: pusb_interface is NULL\n"); 3013 + return -EFAULT; 3014 + } 3015 + /*---------------------------------------------------------------------------*/ 3016 + /* 3017 + * GET POINTER TO STRUCTURE usb_device 3018 + */ 3019 + /*---------------------------------------------------------------------------*/ 3020 + pusb_device1 = container_of(pusb_interface->dev.parent, \ 3021 + struct usb_device, dev); 3022 + if ((struct usb_device *)NULL == pusb_device1) { 3023 + SAY("ERROR: pusb_device1 is NULL\n"); 3024 + return -EFAULT; 3025 + } 3026 + pusb_device = usb_get_dev(pusb_device1); 3027 + if ((struct usb_device *)NULL == pusb_device) { 3028 + SAY("ERROR: pusb_device is NULL\n"); 3029 + return -EFAULT; 3030 + } 3031 + if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) { 3032 + JOT(4, "ERROR: pusb_device1 != pusb_device\n"); 3033 + return -EFAULT; 3034 + } 3035 + 3036 + JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations); 3037 + 3038 + /*---------------------------------------------------------------------------*/ 3039 + pusb_host_interface = pusb_interface->cur_altsetting; 3040 + if (NULL == pusb_host_interface) { 3041 + SAY("ERROR: pusb_host_interface is NULL\n"); 3042 + return -EFAULT; 3043 + } 3044 + pusb_interface_descriptor = &(pusb_host_interface->desc); 3045 + if (NULL == pusb_interface_descriptor) { 3046 + SAY("ERROR: pusb_interface_descriptor is NULL\n"); 3047 + return -EFAULT; 3048 + } 3049 + /*---------------------------------------------------------------------------*/ 3050 + /* 3051 + * GET PROPERTIES OF PROBED INTERFACE 3052 + */ 3053 + /*---------------------------------------------------------------------------*/ 3054 + bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber; 3055 + bInterfaceClass = pusb_interface_descriptor->bInterfaceClass; 3056 + bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass; 3057 + 3058 + JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n", \ 3059 + bInterfaceNumber, pusb_interface->num_altsetting); 3060 + JOT(4, "intf[%i]: pusb_interface->cur_altsetting - " \ 3061 + "pusb_interface->altsetting=%li\n", bInterfaceNumber, \ 3062 + (long int)(pusb_interface->cur_altsetting - \ 3063 + pusb_interface->altsetting)); 3064 + switch (bInterfaceClass) { 3065 + case USB_CLASS_AUDIO: { 3066 + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n", \ 3067 + bInterfaceNumber, bInterfaceClass); break; 3068 + } 3069 + case USB_CLASS_VIDEO: { 3070 + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n", \ 3071 + bInterfaceNumber, bInterfaceClass); break; 3072 + } 3073 + case USB_CLASS_VENDOR_SPEC: { 3074 + JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n", \ 3075 + bInterfaceNumber, bInterfaceClass); break; 3076 + } 3077 + default: 3078 + break; 3079 + } 3080 + switch (bInterfaceSubClass) { 3081 + case 0x01: { 3082 + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n", \ 3083 + bInterfaceNumber, bInterfaceSubClass); break; 3084 + } 3085 + case 0x02: { 3086 + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n", \ 3087 + bInterfaceNumber, bInterfaceSubClass); break; 3088 + } 3089 + case 0x03: { 3090 + JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n", \ 3091 + bInterfaceNumber, bInterfaceSubClass); break; 3092 + } 3093 + default: 3094 + break; 3095 + } 3096 + /*---------------------------------------------------------------------------*/ 3097 + pusb_interface_assoc_descriptor = pusb_interface->intf_assoc; 3098 + if (NULL != pusb_interface_assoc_descriptor) { 3099 + JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n", \ 3100 + bInterfaceNumber, \ 3101 + pusb_interface_assoc_descriptor->bFirstInterface, \ 3102 + pusb_interface_assoc_descriptor->bInterfaceCount); 3103 + } else { 3104 + JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \ 3105 + bInterfaceNumber); 3106 + } 3107 + /*---------------------------------------------------------------------------*/ 3108 + /* 3109 + * A NEW struct easycap IS ALWAYS ALLOCATED WHEN INTERFACE 0 IS PROBED. 3110 + * IT IS NOT POSSIBLE HERE TO FREE ANY EXISTING struct easycap. THIS 3111 + * SHOULD HAVE BEEN DONE BY easycap_delete() WHEN THE DEVICE WAS PHYSICALLY 3112 + * UNPLUGGED. 3113 + */ 3114 + /*---------------------------------------------------------------------------*/ 3115 + if (0 == bInterfaceNumber) { 3116 + peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); 3117 + if (NULL == peasycap) { 3118 + SAY("ERROR: Could not allocate peasycap\n"); 3119 + return -ENOMEM; 3120 + } else { 3121 + peasycap->allocation_video_struct = sizeof(struct easycap); 3122 + peasycap->allocation_video_page = 0; 3123 + peasycap->allocation_video_urb = 0; 3124 + peasycap->allocation_audio_struct = 0; 3125 + peasycap->allocation_audio_page = 0; 3126 + peasycap->allocation_audio_urb = 0; 3127 + } 3128 + /*---------------------------------------------------------------------------*/ 3129 + /* 3130 + * INITIALIZE THE NEW easycap STRUCTURE. 3131 + * NO PARAMETERS ARE SPECIFIED HERE REQUIRING THE SETTING OF REGISTERS. 3132 + * THAT IS DONE FIRST BY easycap_open() AND LATER BY easycap_ioctl(). 3133 + */ 3134 + /*---------------------------------------------------------------------------*/ 3135 + peasycap->pusb_device = pusb_device; 3136 + peasycap->pusb_interface = pusb_interface; 3137 + 3138 + kref_init(&peasycap->kref); 3139 + JOT(8, "intf[%i]: after kref_init(..._video) " \ 3140 + "%i=peasycap->kref.refcount.counter\n", \ 3141 + bInterfaceNumber, peasycap->kref.refcount.counter); 3142 + 3143 + init_waitqueue_head(&(peasycap->wq_video)); 3144 + init_waitqueue_head(&(peasycap->wq_audio)); 3145 + 3146 + mutex_init(&(peasycap->mutex_timeval0)); 3147 + mutex_init(&(peasycap->mutex_timeval1)); 3148 + 3149 + for (k = 0; k < FRAME_BUFFER_MANY; k++) 3150 + mutex_init(&(peasycap->mutex_mmap_video[k])); 3151 + 3152 + peasycap->ilk = 0; 3153 + peasycap->microphone = false; 3154 + 3155 + peasycap->video_interface = -1; 3156 + peasycap->video_altsetting_on = -1; 3157 + peasycap->video_altsetting_off = -1; 3158 + peasycap->video_endpointnumber = -1; 3159 + peasycap->video_isoc_maxframesize = -1; 3160 + peasycap->video_isoc_buffer_size = -1; 3161 + 3162 + peasycap->audio_interface = -1; 3163 + peasycap->audio_altsetting_on = -1; 3164 + peasycap->audio_altsetting_off = -1; 3165 + peasycap->audio_endpointnumber = -1; 3166 + peasycap->audio_isoc_maxframesize = -1; 3167 + peasycap->audio_isoc_buffer_size = -1; 3168 + 3169 + peasycap->frame_buffer_many = FRAME_BUFFER_MANY; 3170 + 3171 + if ((struct mutex *)NULL == &(peasycap->mutex_mmap_video[0])) { 3172 + SAY("ERROR: &(peasycap->mutex_mmap_video[%i]) is NULL\n", 0); 3173 + return -EFAULT; 3174 + } 3175 + /*---------------------------------------------------------------------------*/ 3176 + /* 3177 + * DYNAMICALLY FILL IN THE AVAILABLE FORMATS. 3178 + */ 3179 + /*---------------------------------------------------------------------------*/ 3180 + rc = fillin_formats(); 3181 + if (0 > rc) { 3182 + SAY("ERROR: fillin_formats() returned %i\n", rc); 3183 + return -EFAULT; 3184 + } 3185 + JOT(4, "%i formats available\n", rc); 3186 + } else { 3187 + /*---------------------------------------------------------------------------*/ 3188 + if ((struct easycap *)NULL == peasycap) { 3189 + SAY("ERROR: peasycap is NULL " \ 3190 + "when probing interface %i\n", \ 3191 + bInterfaceNumber); 3192 + return -EFAULT; 3193 + } 3194 + 3195 + JOT(8, "kref_get() with %i=peasycap->kref.refcount.counter\n", \ 3196 + (int)peasycap->kref.refcount.counter); 3197 + kref_get(&peasycap->kref); 3198 + } 3199 + /*---------------------------------------------------------------------------*/ 3200 + if ((USB_CLASS_VIDEO == bInterfaceClass) || \ 3201 + (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) { 3202 + if (-1 == peasycap->video_interface) { 3203 + peasycap->video_interface = bInterfaceNumber; 3204 + JOT(4, "setting peasycap->video_interface=%i\n", \ 3205 + peasycap->video_interface); 3206 + } else { 3207 + if (peasycap->video_interface != bInterfaceNumber) { 3208 + SAY("ERROR: attempting to reset " \ 3209 + "peasycap->video_interface\n"); 3210 + SAY("...... continuing with " \ 3211 + "%i=peasycap->video_interface\n", \ 3212 + peasycap->video_interface); 3213 + } 3214 + } 3215 + } else if ((USB_CLASS_AUDIO == bInterfaceClass) && \ 3216 + (0x02 == bInterfaceSubClass)) { 3217 + if (-1 == peasycap->audio_interface) { 3218 + peasycap->audio_interface = bInterfaceNumber; 3219 + JOT(4, "setting peasycap->audio_interface=%i\n", \ 3220 + peasycap->audio_interface); 3221 + } else { 3222 + if (peasycap->audio_interface != bInterfaceNumber) { 3223 + SAY("ERROR: attempting to reset " \ 3224 + "peasycap->audio_interface\n"); 3225 + SAY("...... continuing with " \ 3226 + "%i=peasycap->audio_interface\n", \ 3227 + peasycap->audio_interface); 3228 + } 3229 + } 3230 + } 3231 + /*---------------------------------------------------------------------------*/ 3232 + /* 3233 + * INVESTIGATE ALL ALTSETTINGS. 3234 + * DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS. 3235 + */ 3236 + /*---------------------------------------------------------------------------*/ 3237 + isokalt = 0; 3238 + isokepn = 0; 3239 + isokmps = 0; 3240 + 3241 + for (i = 0; i < pusb_interface->num_altsetting; i++) { 3242 + pusb_host_interface = &(pusb_interface->altsetting[i]); 3243 + if ((struct usb_host_interface *)NULL == pusb_host_interface) { 3244 + SAY("ERROR: pusb_host_interface is NULL\n"); 3245 + return -EFAULT; 3246 + } 3247 + pusb_interface_descriptor = &(pusb_host_interface->desc); 3248 + if ((struct usb_interface_descriptor *)NULL == \ 3249 + pusb_interface_descriptor) { 3250 + SAY("ERROR: pusb_interface_descriptor is NULL\n"); 3251 + return -EFAULT; 3252 + } 3253 + 3254 + JOT(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n", \ 3255 + bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType); 3256 + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n", \ 3257 + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber); 3258 + JOT(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n", \ 3259 + bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting); 3260 + JOT(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n", \ 3261 + bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints); 3262 + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n", \ 3263 + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass); 3264 + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n", \ 3265 + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass); 3266 + JOT(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n", \ 3267 + bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol); 3268 + JOT(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n", \ 3269 + bInterfaceNumber, i, pusb_interface_descriptor->iInterface); 3270 + 3271 + ISOCwMaxPacketSize = -1; 3272 + BULKwMaxPacketSize = -1; 3273 + INTwMaxPacketSize = -1; 3274 + CTRLwMaxPacketSize = -1; 3275 + ISOCbEndpointAddress = 0; 3276 + INTbEndpointAddress = 0; 3277 + 3278 + if (0 == pusb_interface_descriptor->bNumEndpoints) 3279 + JOT(4, "intf[%i]alt[%i] has no endpoints\n", \ 3280 + bInterfaceNumber, i); 3281 + /*---------------------------------------------------------------------------*/ 3282 + for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) { 3283 + pepd = &(pusb_host_interface->endpoint[j].desc); 3284 + if ((struct usb_endpoint_descriptor *)NULL == pepd) { 3285 + SAY("ERROR: pepd is NULL.\n"); 3286 + SAY("...... skipping\n"); 3287 + continue; 3288 + } 3289 + wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize); 3290 + bEndpointAddress = pepd->bEndpointAddress; 3291 + 3292 + JOT(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n", \ 3293 + bInterfaceNumber, i, j, \ 3294 + pepd->bEndpointAddress); 3295 + JOT(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n", \ 3296 + bInterfaceNumber, i, j, \ 3297 + pepd->bmAttributes); 3298 + JOT(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n", \ 3299 + bInterfaceNumber, i, j, \ 3300 + pepd->wMaxPacketSize); 3301 + JOT(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n", 3302 + bInterfaceNumber, i, j, \ 3303 + pepd->bInterval); 3304 + 3305 + if (pepd->bEndpointAddress & USB_DIR_IN) { 3306 + JOT(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",\ 3307 + bInterfaceNumber, i, j); 3308 + isin = 1; 3309 + } else { 3310 + JOT(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",\ 3311 + bInterfaceNumber, i, j); 3312 + SAY("ERROR: OUT endpoint unexpected\n"); 3313 + SAY("...... continuing\n"); 3314 + isin = 0; 3315 + } 3316 + if ((pepd->bmAttributes & \ 3317 + USB_ENDPOINT_XFERTYPE_MASK) == \ 3318 + USB_ENDPOINT_XFER_ISOC) { 3319 + JOT(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",\ 3320 + bInterfaceNumber, i, j); 3321 + if (isin) { 3322 + switch (bInterfaceClass) { 3323 + case USB_CLASS_VIDEO: 3324 + case USB_CLASS_VENDOR_SPEC: { 3325 + if (!peasycap) { 3326 + SAY("MISTAKE: " \ 3327 + "peasycap is NULL\n"); 3328 + return -EFAULT; 3329 + } 3330 + if (pepd->wMaxPacketSize) { 3331 + if (8 > isokalt) { 3332 + okalt[isokalt] = i; 3333 + JOT(4,\ 3334 + "%i=okalt[%i]\n", \ 3335 + okalt[isokalt], \ 3336 + isokalt); 3337 + isokalt++; 3338 + } 3339 + if (8 > isokepn) { 3340 + okepn[isokepn] = \ 3341 + pepd->\ 3342 + bEndpointAddress & \ 3343 + 0x0F; 3344 + JOT(4,\ 3345 + "%i=okepn[%i]\n", \ 3346 + okepn[isokepn], \ 3347 + isokepn); 3348 + isokepn++; 3349 + } 3350 + if (8 > isokmps) { 3351 + okmps[isokmps] = \ 3352 + le16_to_cpu(pepd->\ 3353 + wMaxPacketSize); 3354 + JOT(4,\ 3355 + "%i=okmps[%i]\n", \ 3356 + okmps[isokmps], \ 3357 + isokmps); 3358 + isokmps++; 3359 + } 3360 + } else { 3361 + if (-1 == peasycap->\ 3362 + video_altsetting_off) { 3363 + peasycap->\ 3364 + video_altsetting_off =\ 3365 + i; 3366 + JOT(4, "%i=video_" \ 3367 + "altsetting_off " \ 3368 + "<====\n", \ 3369 + peasycap->\ 3370 + video_altsetting_off); 3371 + } else { 3372 + SAY("ERROR: peasycap" \ 3373 + "->video_altsetting_" \ 3374 + "off already set\n"); 3375 + SAY("...... " \ 3376 + "continuing with " \ 3377 + "%i=peasycap->video_" \ 3378 + "altsetting_off\n", \ 3379 + peasycap->\ 3380 + video_altsetting_off); 3381 + } 3382 + } 3383 + break; 3384 + } 3385 + case USB_CLASS_AUDIO: { 3386 + if (0x02 != bInterfaceSubClass) 3387 + break; 3388 + if (!peasycap) { 3389 + SAY("MISTAKE: " \ 3390 + "peasycap is NULL\n"); 3391 + return -EFAULT; 3392 + } 3393 + if (pepd->wMaxPacketSize) { 3394 + if (8 > isokalt) { 3395 + okalt[isokalt] = i ; 3396 + JOT(4,\ 3397 + "%i=okalt[%i]\n", \ 3398 + okalt[isokalt], \ 3399 + isokalt); 3400 + isokalt++; 3401 + } 3402 + if (8 > isokepn) { 3403 + okepn[isokepn] = \ 3404 + pepd->\ 3405 + bEndpointAddress & \ 3406 + 0x0F; 3407 + JOT(4,\ 3408 + "%i=okepn[%i]\n", \ 3409 + okepn[isokepn], \ 3410 + isokepn); 3411 + isokepn++; 3412 + } 3413 + if (8 > isokmps) { 3414 + okmps[isokmps] = \ 3415 + le16_to_cpu(pepd->\ 3416 + wMaxPacketSize); 3417 + JOT(4,\ 3418 + "%i=okmps[%i]\n",\ 3419 + okmps[isokmps], \ 3420 + isokmps); 3421 + isokmps++; 3422 + } 3423 + } else { 3424 + if (-1 == peasycap->\ 3425 + audio_altsetting_off) { 3426 + peasycap->\ 3427 + audio_altsetting_off =\ 3428 + i; 3429 + JOT(4, "%i=audio_" \ 3430 + "altsetting_off " \ 3431 + "<====\n", \ 3432 + peasycap->\ 3433 + audio_altsetting_off); 3434 + } else { 3435 + SAY("ERROR: peasycap" \ 3436 + "->audio_altsetting_" \ 3437 + "off already set\n"); 3438 + SAY("...... " \ 3439 + "continuing with " \ 3440 + "%i=peasycap->\ 3441 + audio_altsetting_" \ 3442 + "off\n", 3443 + peasycap->\ 3444 + audio_altsetting_off); 3445 + } 3446 + } 3447 + break; 3448 + } 3449 + default: 3450 + break; 3451 + } 3452 + } 3453 + } else if ((pepd->bmAttributes & \ 3454 + USB_ENDPOINT_XFERTYPE_MASK) ==\ 3455 + USB_ENDPOINT_XFER_BULK) { 3456 + JOT(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",\ 3457 + bInterfaceNumber, i, j); 3458 + } else if ((pepd->bmAttributes & \ 3459 + USB_ENDPOINT_XFERTYPE_MASK) ==\ 3460 + USB_ENDPOINT_XFER_INT) { 3461 + JOT(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",\ 3462 + bInterfaceNumber, i, j); 3463 + } else { 3464 + JOT(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",\ 3465 + bInterfaceNumber, i, j); 3466 + } 3467 + if (0 == pepd->wMaxPacketSize) { 3468 + JOT(4, "intf[%i]alt[%i]end[%i] " \ 3469 + "has zero packet size\n", \ 3470 + bInterfaceNumber, i, j); 3471 + } 3472 + } 3473 + } 3474 + /*---------------------------------------------------------------------------*/ 3475 + /* 3476 + * PERFORM INITIALIZATION OF THE PROBED INTERFACE 3477 + */ 3478 + /*---------------------------------------------------------------------------*/ 3479 + JOT(4, "initialization begins for interface %i\n", \ 3480 + pusb_interface_descriptor->bInterfaceNumber); 3481 + switch (bInterfaceNumber) { 3482 + /*---------------------------------------------------------------------------*/ 3483 + /* 3484 + * INTERFACE 0 IS THE VIDEO INTERFACE 3485 + */ 3486 + /*---------------------------------------------------------------------------*/ 3487 + case 0: { 3488 + if (!peasycap) { 3489 + SAY("MISTAKE: peasycap is NULL\n"); 3490 + return -EFAULT; 3491 + } 3492 + if (!isokalt) { 3493 + SAY("ERROR: no viable video_altsetting_on\n"); 3494 + return -ENOENT; 3495 + } else { 3496 + peasycap->video_altsetting_on = okalt[isokalt - 1]; 3497 + JOT(4, "%i=video_altsetting_on <====\n", \ 3498 + peasycap->video_altsetting_on); 3499 + } 3500 + if (!isokepn) { 3501 + SAY("ERROR: no viable video_endpointnumber\n"); 3502 + return -ENOENT; 3503 + } else { 3504 + peasycap->video_endpointnumber = okepn[isokepn - 1]; 3505 + JOT(4, "%i=video_endpointnumber\n", \ 3506 + peasycap->video_endpointnumber); 3507 + } 3508 + if (!isokmps) { 3509 + SAY("ERROR: no viable video_maxpacketsize\n"); 3510 + return -ENOENT; 3511 + /*---------------------------------------------------------------------------*/ 3512 + /* 3513 + * DECIDE THE VIDEO STREAMING PARAMETERS 3514 + */ 3515 + /*---------------------------------------------------------------------------*/ 3516 + } else { 3517 + maxpacketsize = okmps[isokmps - 1] - 1024; 3518 + if (USB_2_0_MAXPACKETSIZE > maxpacketsize) { 3519 + peasycap->video_isoc_maxframesize = maxpacketsize; 3520 + } else { 3521 + peasycap->video_isoc_maxframesize = \ 3522 + USB_2_0_MAXPACKETSIZE; 3523 + } 3524 + JOT(4, "%i=video_isoc_maxframesize\n", \ 3525 + peasycap->video_isoc_maxframesize); 3526 + if (0 >= peasycap->video_isoc_maxframesize) { 3527 + SAY("ERROR: bad video_isoc_maxframesize\n"); 3528 + return -ENOENT; 3529 + } 3530 + peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC; 3531 + JOT(4, "%i=video_isoc_framesperdesc\n", \ 3532 + peasycap->video_isoc_framesperdesc); 3533 + if (0 >= peasycap->video_isoc_framesperdesc) { 3534 + SAY("ERROR: bad video_isoc_framesperdesc\n"); 3535 + return -ENOENT; 3536 + } 3537 + peasycap->video_isoc_buffer_size = \ 3538 + peasycap->video_isoc_maxframesize * \ 3539 + peasycap->video_isoc_framesperdesc; 3540 + JOT(4, "%i=video_isoc_buffer_size\n", \ 3541 + peasycap->video_isoc_buffer_size); 3542 + if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < \ 3543 + peasycap->video_isoc_buffer_size) { 3544 + SAY("MISTAKE: " \ 3545 + "peasycap->video_isoc_buffer_size too big\n"); 3546 + return -EFAULT; 3547 + } 3548 + } 3549 + /*---------------------------------------------------------------------------*/ 3550 + if (-1 == peasycap->video_interface) { 3551 + SAY("MISTAKE: video_interface is unset\n"); 3552 + return -EFAULT; 3553 + } 3554 + if (-1 == peasycap->video_altsetting_on) { 3555 + SAY("MISTAKE: video_altsetting_on is unset\n"); 3556 + return -EFAULT; 3557 + } 3558 + if (-1 == peasycap->video_altsetting_off) { 3559 + SAY("MISTAKE: video_interface_off is unset\n"); 3560 + return -EFAULT; 3561 + } 3562 + if (-1 == peasycap->video_endpointnumber) { 3563 + SAY("MISTAKE: video_endpointnumber is unset\n"); 3564 + return -EFAULT; 3565 + } 3566 + if (-1 == peasycap->video_isoc_maxframesize) { 3567 + SAY("MISTAKE: video_isoc_maxframesize is unset\n"); 3568 + return -EFAULT; 3569 + } 3570 + if (-1 == peasycap->video_isoc_buffer_size) { 3571 + SAY("MISTAKE: video_isoc_buffer_size is unset\n"); 3572 + return -EFAULT; 3573 + } 3574 + /*---------------------------------------------------------------------------*/ 3575 + /* 3576 + * ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST. 3577 + */ 3578 + /*---------------------------------------------------------------------------*/ 3579 + INIT_LIST_HEAD(&(peasycap->urb_video_head)); 3580 + peasycap->purb_video_head = &(peasycap->urb_video_head); 3581 + /*---------------------------------------------------------------------------*/ 3582 + JOT(4, "allocating %i frame buffers of size %li\n", \ 3583 + FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE); 3584 + JOT(4, ".... each scattered over %li pages\n", \ 3585 + FRAME_BUFFER_SIZE/PAGE_SIZE); 3586 + 3587 + for (k = 0; k < FRAME_BUFFER_MANY; k++) { 3588 + for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) { 3589 + if ((void *)NULL != peasycap->frame_buffer[k][m].pgo) 3590 + SAY("attempting to reallocate frame " \ 3591 + " buffers\n"); 3592 + else { 3593 + pbuf = (void *)__get_free_page(GFP_KERNEL); 3594 + if ((void *)NULL == pbuf) { 3595 + SAY("ERROR: Could not allocate frame "\ 3596 + "buffer %i page %i\n", k, m); 3597 + return -ENOMEM; 3598 + } else 3599 + peasycap->allocation_video_page += 1; 3600 + peasycap->frame_buffer[k][m].pgo = pbuf; 3601 + } 3602 + peasycap->frame_buffer[k][m].pto = \ 3603 + peasycap->frame_buffer[k][m].pgo; 3604 + } 3605 + } 3606 + 3607 + peasycap->frame_fill = 0; 3608 + peasycap->frame_read = 0; 3609 + JOT(4, "allocation of frame buffers done: %i pages\n", k * \ 3610 + m); 3611 + /*---------------------------------------------------------------------------*/ 3612 + JOT(4, "allocating %i field buffers of size %li\n", \ 3613 + FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE); 3614 + JOT(4, ".... each scattered over %li pages\n", \ 3615 + FIELD_BUFFER_SIZE/PAGE_SIZE); 3616 + 3617 + for (k = 0; k < FIELD_BUFFER_MANY; k++) { 3618 + for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) { 3619 + if ((void *)NULL != peasycap->field_buffer[k][m].pgo) { 3620 + SAY("ERROR: attempting to reallocate " \ 3621 + "field buffers\n"); 3622 + } else { 3623 + pbuf = (void *) __get_free_page(GFP_KERNEL); 3624 + if ((void *)NULL == pbuf) { 3625 + SAY("ERROR: Could not allocate field" \ 3626 + " buffer %i page %i\n", k, m); 3627 + return -ENOMEM; 3628 + } 3629 + else 3630 + peasycap->allocation_video_page += 1; 3631 + peasycap->field_buffer[k][m].pgo = pbuf; 3632 + } 3633 + peasycap->field_buffer[k][m].pto = \ 3634 + peasycap->field_buffer[k][m].pgo; 3635 + } 3636 + peasycap->field_buffer[k][0].kount = 0x0200; 3637 + } 3638 + peasycap->field_fill = 0; 3639 + peasycap->field_page = 0; 3640 + peasycap->field_read = 0; 3641 + JOT(4, "allocation of field buffers done: %i pages\n", k * \ 3642 + m); 3643 + /*---------------------------------------------------------------------------*/ 3644 + JOT(4, "allocating %i isoc video buffers of size %i\n", \ 3645 + VIDEO_ISOC_BUFFER_MANY, \ 3646 + peasycap->video_isoc_buffer_size); 3647 + JOT(4, ".... each occupying contiguous memory pages\n"); 3648 + 3649 + for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { 3650 + pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER); 3651 + if (NULL == pbuf) { 3652 + SAY("ERROR: Could not allocate isoc video buffer " \ 3653 + "%i\n", k); 3654 + return -ENOMEM; 3655 + } else 3656 + peasycap->allocation_video_page += \ 3657 + ((unsigned int)(0x01 << VIDEO_ISOC_ORDER)); 3658 + 3659 + peasycap->video_isoc_buffer[k].pgo = pbuf; 3660 + peasycap->video_isoc_buffer[k].pto = pbuf + \ 3661 + peasycap->video_isoc_buffer_size; 3662 + peasycap->video_isoc_buffer[k].kount = k; 3663 + } 3664 + JOT(4, "allocation of isoc video buffers done: %i pages\n", \ 3665 + k * (0x01 << VIDEO_ISOC_ORDER)); 3666 + /*---------------------------------------------------------------------------*/ 3667 + /* 3668 + * ALLOCATE AND INITIALIZE MULTIPLE struct urb ... 3669 + */ 3670 + /*---------------------------------------------------------------------------*/ 3671 + JOT(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY); 3672 + JOT(4, "using %i=peasycap->video_isoc_framesperdesc\n", \ 3673 + peasycap->video_isoc_framesperdesc); 3674 + JOT(4, "using %i=peasycap->video_isoc_maxframesize\n", \ 3675 + peasycap->video_isoc_maxframesize); 3676 + JOT(4, "using %i=peasycap->video_isoc_buffer_sizen", \ 3677 + peasycap->video_isoc_buffer_size); 3678 + 3679 + for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) { 3680 + purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, \ 3681 + GFP_KERNEL); 3682 + if (NULL == purb) { 3683 + SAY("ERROR: usb_alloc_urb returned NULL for buffer " \ 3684 + "%i\n", k); 3685 + return -ENOMEM; 3686 + } else 3687 + peasycap->allocation_video_urb += 1; 3688 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 3689 + pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); 3690 + if (NULL == pdata_urb) { 3691 + SAY("ERROR: Could not allocate struct data_urb.\n"); 3692 + return -ENOMEM; 3693 + } else 3694 + peasycap->allocation_video_struct += \ 3695 + sizeof(struct data_urb); 3696 + 3697 + pdata_urb->purb = purb; 3698 + pdata_urb->isbuf = k; 3699 + pdata_urb->length = 0; 3700 + list_add_tail(&(pdata_urb->list_head), \ 3701 + peasycap->purb_video_head); 3702 + /*---------------------------------------------------------------------------*/ 3703 + /* 3704 + * ... AND INITIALIZE THEM 3705 + */ 3706 + /*---------------------------------------------------------------------------*/ 3707 + if (!k) { 3708 + JOT(4, "initializing video urbs thus:\n"); 3709 + JOT(4, " purb->interval = 1;\n"); 3710 + JOT(4, " purb->dev = peasycap->pusb_device;\n"); 3711 + JOT(4, " purb->pipe = usb_rcvisocpipe" \ 3712 + "(peasycap->pusb_device,%i);\n", \ 3713 + peasycap->video_endpointnumber); 3714 + JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); 3715 + JOT(4, " purb->transfer_buffer = peasycap->" \ 3716 + "video_isoc_buffer[.].pgo;\n"); 3717 + JOT(4, " purb->transfer_buffer_length = %i;\n", \ 3718 + peasycap->video_isoc_buffer_size); 3719 + JOT(4, " purb->complete = easycap_complete;\n"); 3720 + JOT(4, " purb->context = peasycap;\n"); 3721 + JOT(4, " purb->start_frame = 0;\n"); 3722 + JOT(4, " purb->number_of_packets = %i;\n", \ 3723 + peasycap->video_isoc_framesperdesc); 3724 + JOT(4, " for (j = 0; j < %i; j++)\n", \ 3725 + peasycap->video_isoc_framesperdesc); 3726 + JOT(4, " {\n"); 3727 + JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\ 3728 + peasycap->video_isoc_maxframesize); 3729 + JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \ 3730 + peasycap->video_isoc_maxframesize); 3731 + JOT(4, " }\n"); 3732 + } 3733 + 3734 + purb->interval = 1; 3735 + purb->dev = peasycap->pusb_device; 3736 + purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \ 3737 + peasycap->video_endpointnumber); 3738 + purb->transfer_flags = URB_ISO_ASAP; 3739 + purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo; 3740 + purb->transfer_buffer_length = \ 3741 + peasycap->video_isoc_buffer_size; 3742 + purb->complete = easycap_complete; 3743 + purb->context = peasycap; 3744 + purb->start_frame = 0; 3745 + purb->number_of_packets = peasycap->video_isoc_framesperdesc; 3746 + for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) { 3747 + purb->iso_frame_desc[j].offset = j * \ 3748 + peasycap->video_isoc_maxframesize; 3749 + purb->iso_frame_desc[j].length = \ 3750 + peasycap->video_isoc_maxframesize; 3751 + } 3752 + } 3753 + JOT(4, "allocation of %i struct urb done.\n", k); 3754 + /*--------------------------------------------------------------------------*/ 3755 + /* 3756 + * SAVE POINTER peasycap IN THIS INTERFACE. 3757 + */ 3758 + /*--------------------------------------------------------------------------*/ 3759 + usb_set_intfdata(pusb_interface, peasycap); 3760 + /*--------------------------------------------------------------------------*/ 3761 + /* 3762 + * THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. 3763 + */ 3764 + /*--------------------------------------------------------------------------*/ 3765 + #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 3766 + if (0 != (usb_register_dev(pusb_interface, &easycap_class))) { 3767 + err("Not able to get a minor for this device"); 3768 + usb_set_intfdata(pusb_interface, NULL); 3769 + return -ENODEV; 3770 + } else 3771 + (peasycap->registered_video)++; 3772 + SAY("easycap attached to minor #%d\n", pusb_interface->minor); 3773 + break; 3774 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 3775 + #else 3776 + pvideo_device = (struct video_device *)\ 3777 + kzalloc(sizeof(struct video_device), GFP_KERNEL); 3778 + if ((struct video_device *)NULL == pvideo_device) { 3779 + SAY("ERROR: Could not allocate structure video_device\n"); 3780 + return -ENOMEM; 3781 + } 3782 + if (VIDEO_DEVICE_MANY <= video_device_many) { 3783 + SAY("ERROR: Too many /dev/videos\n"); 3784 + return -ENOMEM; 3785 + } 3786 + pvideo_array[video_device_many] = pvideo_device; video_device_many++; 3787 + 3788 + strcpy(&pvideo_device->name[0], "easycapdc60"); 3789 + #if defined(EASYCAP_NEEDS_V4L2_FOPS) 3790 + pvideo_device->fops = &v4l2_fops; 3791 + #else 3792 + pvideo_device->fops = &easycap_fops; 3793 + #endif /*EASYCAP_NEEDS_V4L2_FOPS*/ 3794 + pvideo_device->minor = -1; 3795 + pvideo_device->release = (void *)(&videodev_release); 3796 + 3797 + video_set_drvdata(pvideo_device, (void *)peasycap); 3798 + 3799 + rc = video_register_device(pvideo_device, VFL_TYPE_GRABBER, -1); 3800 + if (0 != rc) { 3801 + err("Not able to register with videodev"); 3802 + videodev_release(pvideo_device); 3803 + return -ENODEV; 3804 + } else { 3805 + peasycap->pvideo_device = pvideo_device; 3806 + (peasycap->registered_video)++; 3807 + JOT(4, "registered with videodev: %i=minor\n", \ 3808 + pvideo_device->minor); 3809 + } 3810 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 3811 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 3812 + break; 3813 + } 3814 + /*--------------------------------------------------------------------------*/ 3815 + /* 3816 + * INTERFACE 1 IS THE AUDIO CONTROL INTERFACE 3817 + * INTERFACE 2 IS THE AUDIO STREAMING INTERFACE 3818 + */ 3819 + /*--------------------------------------------------------------------------*/ 3820 + case 1: { 3821 + /*--------------------------------------------------------------------------*/ 3822 + /* 3823 + * SAVE POINTER peasycap IN INTERFACE 1 3824 + */ 3825 + /*--------------------------------------------------------------------------*/ 3826 + usb_set_intfdata(pusb_interface, peasycap); 3827 + JOT(4, "no initialization required for interface %i\n", \ 3828 + pusb_interface_descriptor->bInterfaceNumber); 3829 + break; 3830 + } 3831 + /*--------------------------------------------------------------------------*/ 3832 + case 2: { 3833 + if (!peasycap) { 3834 + SAY("MISTAKE: peasycap is NULL\n"); 3835 + return -EFAULT; 3836 + } 3837 + if (!isokalt) { 3838 + SAY("ERROR: no viable audio_altsetting_on\n"); 3839 + return -ENOENT; 3840 + } else { 3841 + peasycap->audio_altsetting_on = okalt[isokalt - 1]; 3842 + JOT(4, "%i=audio_altsetting_on <====\n", \ 3843 + peasycap->audio_altsetting_on); 3844 + } 3845 + if (!isokepn) { 3846 + SAY("ERROR: no viable audio_endpointnumber\n"); 3847 + return -ENOENT; 3848 + } else { 3849 + peasycap->audio_endpointnumber = okepn[isokepn - 1]; 3850 + JOT(4, "%i=audio_endpointnumber\n", \ 3851 + peasycap->audio_endpointnumber); 3852 + } 3853 + if (!isokmps) { 3854 + SAY("ERROR: no viable audio_maxpacketsize\n"); 3855 + return -ENOENT; 3856 + } else { 3857 + peasycap->audio_isoc_maxframesize = okmps[isokmps - 1]; 3858 + JOT(4, "%i=audio_isoc_maxframesize\n", \ 3859 + peasycap->audio_isoc_maxframesize); 3860 + if (0 >= peasycap->audio_isoc_maxframesize) { 3861 + SAY("ERROR: bad audio_isoc_maxframesize\n"); 3862 + return -ENOENT; 3863 + } 3864 + if (9 == peasycap->audio_isoc_maxframesize) { 3865 + peasycap->ilk |= 0x02; 3866 + SAY("hardware is FOUR-CVBS\n"); 3867 + peasycap->microphone = true; 3868 + audio_pages_per_fragment = 2; 3869 + } else if (256 == peasycap->audio_isoc_maxframesize) { 3870 + peasycap->ilk &= ~0x02; 3871 + SAY("hardware is CVBS+S-VIDEO\n"); 3872 + peasycap->microphone = false; 3873 + audio_pages_per_fragment = 4; 3874 + } else { 3875 + SAY("hardware is unidentified:\n"); 3876 + SAY("%i=audio_isoc_maxframesize\n", \ 3877 + peasycap->audio_isoc_maxframesize); 3878 + return -ENOENT; 3879 + } 3880 + 3881 + audio_bytes_per_fragment = audio_pages_per_fragment * \ 3882 + PAGE_SIZE ; 3883 + audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * \ 3884 + audio_pages_per_fragment); 3885 + 3886 + JOT(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY); 3887 + JOT(4, "%6i=audio_pages_per_fragment\n", \ 3888 + audio_pages_per_fragment); 3889 + JOT(4, "%6i=audio_bytes_per_fragment\n", \ 3890 + audio_bytes_per_fragment); 3891 + JOT(4, "%6i=audio_buffer_page_many\n", audio_buffer_page_many); 3892 + 3893 + peasycap->audio_isoc_framesperdesc = 128; 3894 + 3895 + JOT(4, "%i=audio_isoc_framesperdesc\n", \ 3896 + peasycap->audio_isoc_framesperdesc); 3897 + if (0 >= peasycap->audio_isoc_framesperdesc) { 3898 + SAY("ERROR: bad audio_isoc_framesperdesc\n"); 3899 + return -ENOENT; 3900 + } 3901 + 3902 + peasycap->audio_isoc_buffer_size = \ 3903 + peasycap->audio_isoc_maxframesize * \ 3904 + peasycap->audio_isoc_framesperdesc; 3905 + JOT(4, "%i=audio_isoc_buffer_size\n", \ 3906 + peasycap->audio_isoc_buffer_size); 3907 + if (AUDIO_ISOC_BUFFER_SIZE < \ 3908 + peasycap->audio_isoc_buffer_size) { 3909 + SAY("MISTAKE: audio_isoc_buffer_size bigger " 3910 + "than %li=AUDIO_ISOC_BUFFER_SIZE\n", \ 3911 + AUDIO_ISOC_BUFFER_SIZE); 3912 + return -EFAULT; 3913 + } 3914 + } 3915 + 3916 + if (-1 == peasycap->audio_interface) { 3917 + SAY("MISTAKE: audio_interface is unset\n"); 3918 + return -EFAULT; 3919 + } 3920 + if (-1 == peasycap->audio_altsetting_on) { 3921 + SAY("MISTAKE: audio_altsetting_on is unset\n"); 3922 + return -EFAULT; 3923 + } 3924 + if (-1 == peasycap->audio_altsetting_off) { 3925 + SAY("MISTAKE: audio_interface_off is unset\n"); 3926 + return -EFAULT; 3927 + } 3928 + if (-1 == peasycap->audio_endpointnumber) { 3929 + SAY("MISTAKE: audio_endpointnumber is unset\n"); 3930 + return -EFAULT; 3931 + } 3932 + if (-1 == peasycap->audio_isoc_maxframesize) { 3933 + SAY("MISTAKE: audio_isoc_maxframesize is unset\n"); 3934 + return -EFAULT; 3935 + } 3936 + if (-1 == peasycap->audio_isoc_buffer_size) { 3937 + SAY("MISTAKE: audio_isoc_buffer_size is unset\n"); 3938 + return -EFAULT; 3939 + } 3940 + /*---------------------------------------------------------------------------*/ 3941 + /* 3942 + * ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST. 3943 + */ 3944 + /*---------------------------------------------------------------------------*/ 3945 + INIT_LIST_HEAD(&(peasycap->urb_audio_head)); 3946 + peasycap->purb_audio_head = &(peasycap->urb_audio_head); 3947 + 3948 + JOT(4, "allocating an audio buffer\n"); 3949 + JOT(4, ".... scattered over %i pages\n", audio_buffer_page_many); 3950 + 3951 + for (k = 0; k < audio_buffer_page_many; k++) { 3952 + if ((void *)NULL != peasycap->audio_buffer[k].pgo) { 3953 + SAY("ERROR: attempting to reallocate audio buffers\n"); 3954 + } else { 3955 + pbuf = (void *) __get_free_page(GFP_KERNEL); 3956 + if ((void *)NULL == pbuf) { 3957 + SAY("ERROR: Could not allocate audio " \ 3958 + "buffer page %i\n", k); 3959 + return -ENOMEM; 3960 + } else 3961 + peasycap->allocation_audio_page += 1; 3962 + 3963 + peasycap->audio_buffer[k].pgo = pbuf; 3964 + } 3965 + peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo; 3966 + } 3967 + 3968 + peasycap->audio_fill = 0; 3969 + peasycap->audio_read = 0; 3970 + JOT(4, "allocation of audio buffer done: %i pages\n", k); 3971 + /*---------------------------------------------------------------------------*/ 3972 + JOT(4, "allocating %i isoc audio buffers of size %i\n", \ 3973 + AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size); 3974 + JOT(4, ".... each occupying contiguous memory pages\n"); 3975 + 3976 + for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { 3977 + pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER); 3978 + if (NULL == pbuf) { 3979 + SAY("ERROR: Could not allocate isoc audio buffer " \ 3980 + "%i\n", k); 3981 + return -ENOMEM; 3982 + } else 3983 + peasycap->allocation_audio_page += \ 3984 + ((unsigned int)(0x01 << AUDIO_ISOC_ORDER)); 3985 + 3986 + peasycap->audio_isoc_buffer[k].pgo = pbuf; 3987 + peasycap->audio_isoc_buffer[k].pto = pbuf + \ 3988 + peasycap->audio_isoc_buffer_size; 3989 + peasycap->audio_isoc_buffer[k].kount = k; 3990 + } 3991 + JOT(4, "allocation of isoc audio buffers done.\n"); 3992 + /*---------------------------------------------------------------------------*/ 3993 + /* 3994 + * ALLOCATE AND INITIALIZE MULTIPLE struct urb ... 3995 + */ 3996 + /*---------------------------------------------------------------------------*/ 3997 + JOT(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY); 3998 + JOT(4, "using %i=peasycap->audio_isoc_framesperdesc\n", \ 3999 + peasycap->audio_isoc_framesperdesc); 4000 + JOT(4, "using %i=peasycap->audio_isoc_maxframesize\n", \ 4001 + peasycap->audio_isoc_maxframesize); 4002 + JOT(4, "using %i=peasycap->audio_isoc_buffer_size\n", \ 4003 + peasycap->audio_isoc_buffer_size); 4004 + 4005 + for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) { 4006 + purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, \ 4007 + GFP_KERNEL); 4008 + if (NULL == purb) { 4009 + SAY("ERROR: usb_alloc_urb returned NULL for buffer " \ 4010 + "%i\n", k); 4011 + return -ENOMEM; 4012 + } else 4013 + peasycap->allocation_audio_urb += 1 ; 4014 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 4015 + pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL); 4016 + if (NULL == pdata_urb) { 4017 + SAY("ERROR: Could not allocate struct data_urb.\n"); 4018 + return -ENOMEM; 4019 + } else 4020 + peasycap->allocation_audio_struct += \ 4021 + sizeof(struct data_urb); 4022 + 4023 + pdata_urb->purb = purb; 4024 + pdata_urb->isbuf = k; 4025 + pdata_urb->length = 0; 4026 + list_add_tail(&(pdata_urb->list_head), \ 4027 + peasycap->purb_audio_head); 4028 + /*---------------------------------------------------------------------------*/ 4029 + /* 4030 + * ... AND INITIALIZE THEM 4031 + */ 4032 + /*---------------------------------------------------------------------------*/ 4033 + if (!k) { 4034 + JOT(4, "initializing audio urbs thus:\n"); 4035 + JOT(4, " purb->interval = 1;\n"); 4036 + JOT(4, " purb->dev = peasycap->pusb_device;\n"); 4037 + JOT(4, " purb->pipe = usb_rcvisocpipe(peasycap->" \ 4038 + "pusb_device,%i);\n", \ 4039 + peasycap->audio_endpointnumber); 4040 + JOT(4, " purb->transfer_flags = URB_ISO_ASAP;\n"); 4041 + JOT(4, " purb->transfer_buffer = " \ 4042 + "peasycap->audio_isoc_buffer[.].pgo;\n"); 4043 + JOT(4, " purb->transfer_buffer_length = %i;\n", \ 4044 + peasycap->audio_isoc_buffer_size); 4045 + JOT(4, " purb->complete = easysnd_complete;\n"); 4046 + JOT(4, " purb->context = peasycap;\n"); 4047 + JOT(4, " purb->start_frame = 0;\n"); 4048 + JOT(4, " purb->number_of_packets = %i;\n", \ 4049 + peasycap->audio_isoc_framesperdesc); 4050 + JOT(4, " for (j = 0; j < %i; j++)\n", \ 4051 + peasycap->audio_isoc_framesperdesc); 4052 + JOT(4, " {\n"); 4053 + JOT(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\ 4054 + peasycap->audio_isoc_maxframesize); 4055 + JOT(4, " purb->iso_frame_desc[j].length = %i;\n", \ 4056 + peasycap->audio_isoc_maxframesize); 4057 + JOT(4, " }\n"); 4058 + } 4059 + 4060 + purb->interval = 1; 4061 + purb->dev = peasycap->pusb_device; 4062 + purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \ 4063 + peasycap->audio_endpointnumber); 4064 + purb->transfer_flags = URB_ISO_ASAP; 4065 + purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo; 4066 + purb->transfer_buffer_length = \ 4067 + peasycap->audio_isoc_buffer_size; 4068 + purb->complete = easysnd_complete; 4069 + purb->context = peasycap; 4070 + purb->start_frame = 0; 4071 + purb->number_of_packets = peasycap->audio_isoc_framesperdesc; 4072 + for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) { 4073 + purb->iso_frame_desc[j].offset = j * \ 4074 + peasycap->audio_isoc_maxframesize; 4075 + purb->iso_frame_desc[j].length = \ 4076 + peasycap->audio_isoc_maxframesize; 4077 + } 4078 + } 4079 + JOT(4, "allocation of %i struct urb done.\n", k); 4080 + /*---------------------------------------------------------------------------*/ 4081 + /* 4082 + * SAVE POINTER peasycap IN THIS INTERFACE. 4083 + */ 4084 + /*---------------------------------------------------------------------------*/ 4085 + usb_set_intfdata(pusb_interface, peasycap); 4086 + /*---------------------------------------------------------------------------*/ 4087 + /* 4088 + * THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY. 4089 + */ 4090 + /*---------------------------------------------------------------------------*/ 4091 + rc = usb_register_dev(pusb_interface, &easysnd_class); 4092 + if (0 != rc) { 4093 + err("Not able to get a minor for this device."); 4094 + usb_set_intfdata(pusb_interface, NULL); 4095 + return -ENODEV; 4096 + } else 4097 + (peasycap->registered_audio)++; 4098 + /*---------------------------------------------------------------------------*/ 4099 + /* 4100 + * LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO. 4101 + */ 4102 + /*---------------------------------------------------------------------------*/ 4103 + SAY("easysnd attached to minor #%d\n", pusb_interface->minor); 4104 + break; 4105 + } 4106 + /*---------------------------------------------------------------------------*/ 4107 + /* 4108 + * INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED 4109 + */ 4110 + /*---------------------------------------------------------------------------*/ 4111 + default: { 4112 + JOT(4, "ERROR: unexpected interface %i\n", bInterfaceNumber); 4113 + return -EINVAL; 4114 + } 4115 + } 4116 + JOT(4, "ends successfully for interface %i\n", \ 4117 + pusb_interface_descriptor->bInterfaceNumber); 4118 + return 0; 4119 + } 4120 + /*****************************************************************************/ 4121 + /*---------------------------------------------------------------------------*/ 4122 + /* 4123 + * WHEN THIS FUNCTION IS CALLED THE DEVICE HAS ALREADY BEEN PHYSICALLY 4124 + * UNPLUGGED. 4125 + * HENCE peasycap->pusb_device IS NO LONGER VALID AND MUST BE SET TO NULL. 4126 + */ 4127 + /*---------------------------------------------------------------------------*/ 4128 + void 4129 + easycap_usb_disconnect(struct usb_interface *pusb_interface) 4130 + { 4131 + struct usb_host_interface *pusb_host_interface; 4132 + struct usb_interface_descriptor *pusb_interface_descriptor; 4133 + __u8 bInterfaceNumber; 4134 + struct easycap *peasycap; 4135 + 4136 + struct list_head *plist_head; 4137 + struct data_urb *pdata_urb; 4138 + int minor, m; 4139 + 4140 + JOT(4, "\n"); 4141 + 4142 + if ((struct usb_interface *)NULL == pusb_interface) { 4143 + JOT(4, "ERROR: pusb_interface is NULL\n"); 4144 + return; 4145 + } 4146 + pusb_host_interface = pusb_interface->cur_altsetting; 4147 + if ((struct usb_host_interface *)NULL == pusb_host_interface) { 4148 + JOT(4, "ERROR: pusb_host_interface is NULL\n"); 4149 + return; 4150 + } 4151 + pusb_interface_descriptor = &(pusb_host_interface->desc); 4152 + if ((struct usb_interface_descriptor *)NULL == pusb_interface_descriptor) { 4153 + JOT(4, "ERROR: pusb_interface_descriptor is NULL\n"); 4154 + return; 4155 + } 4156 + bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber; 4157 + minor = pusb_interface->minor; 4158 + JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor); 4159 + 4160 + peasycap = usb_get_intfdata(pusb_interface); 4161 + if ((struct easycap *)NULL == peasycap) 4162 + SAY("ERROR: peasycap is NULL\n"); 4163 + else { 4164 + peasycap->pusb_device = (struct usb_device *)NULL; 4165 + switch (bInterfaceNumber) { 4166 + /*---------------------------------------------------------------------------*/ 4167 + case 0: { 4168 + if ((struct list_head *)NULL != peasycap->purb_video_head) { 4169 + JOT(4, "killing video urbs\n"); 4170 + m = 0; 4171 + list_for_each(plist_head, (peasycap->purb_video_head)) 4172 + { 4173 + pdata_urb = list_entry(plist_head, \ 4174 + struct data_urb, list_head); 4175 + if ((struct data_urb *)NULL != pdata_urb) { 4176 + if ((struct urb *)NULL != \ 4177 + pdata_urb->purb) { 4178 + usb_kill_urb(pdata_urb->purb); 4179 + m++; 4180 + } 4181 + } 4182 + } 4183 + JOT(4, "%i video urbs killed\n", m); 4184 + } else 4185 + SAY("ERROR: peasycap->purb_video_head is NULL\n"); 4186 + break; 4187 + } 4188 + /*---------------------------------------------------------------------------*/ 4189 + case 2: { 4190 + if ((struct list_head *)NULL != peasycap->purb_audio_head) { 4191 + JOT(4, "killing audio urbs\n"); 4192 + m = 0; 4193 + list_for_each(plist_head, \ 4194 + (peasycap->purb_audio_head)) { 4195 + pdata_urb = list_entry(plist_head, \ 4196 + struct data_urb, list_head); 4197 + if ((struct data_urb *)NULL != pdata_urb) { 4198 + if ((struct urb *)NULL != \ 4199 + pdata_urb->purb) { 4200 + usb_kill_urb(pdata_urb->purb); 4201 + m++; 4202 + } 4203 + } 4204 + } 4205 + JOT(4, "%i audio urbs killed\n", m); 4206 + } else 4207 + SAY("ERROR: peasycap->purb_audio_head is NULL\n"); 4208 + break; 4209 + } 4210 + /*---------------------------------------------------------------------------*/ 4211 + default: 4212 + break; 4213 + } 4214 + } 4215 + /*--------------------------------------------------------------------------*/ 4216 + /* 4217 + * DEREGISTER 4218 + */ 4219 + /*--------------------------------------------------------------------------*/ 4220 + switch (bInterfaceNumber) { 4221 + case 0: { 4222 + #if (!defined(EASYCAP_IS_VIDEODEV_CLIENT)) 4223 + if ((struct easycap *)NULL == peasycap) { 4224 + SAY("ERROR: peasycap has become NULL\n"); 4225 + } else { 4226 + lock_kernel(); 4227 + usb_deregister_dev(pusb_interface, &easycap_class); 4228 + (peasycap->registered_video)--; 4229 + 4230 + JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); 4231 + unlock_kernel(); 4232 + SAY("easycap detached from minor #%d\n", minor); 4233 + } 4234 + /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ 4235 + #else 4236 + if ((struct easycap *)NULL == peasycap) 4237 + SAY("ERROR: peasycap has become NULL\n"); 4238 + else { 4239 + lock_kernel(); 4240 + video_unregister_device(peasycap->pvideo_device); 4241 + (peasycap->registered_video)--; 4242 + unlock_kernel(); 4243 + JOT(4, "unregistered with videodev: %i=minor\n", \ 4244 + pvideo_device->minor); 4245 + } 4246 + /*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ 4247 + #endif /*EASYCAP_IS_VIDEODEV_CLIENT*/ 4248 + break; 4249 + } 4250 + case 2: { 4251 + lock_kernel(); 4252 + 4253 + usb_deregister_dev(pusb_interface, &easysnd_class); 4254 + if ((struct easycap *)NULL != peasycap) 4255 + (peasycap->registered_audio)--; 4256 + 4257 + JOT(4, "intf[%i]: usb_deregister_dev()\n", bInterfaceNumber); 4258 + unlock_kernel(); 4259 + 4260 + SAY("easysnd detached from minor #%d\n", minor); 4261 + break; 4262 + } 4263 + default: 4264 + break; 4265 + } 4266 + /*---------------------------------------------------------------------------*/ 4267 + /* 4268 + * CALL easycap_delete() IF NO REMAINING REFERENCES TO peasycap 4269 + */ 4270 + /*---------------------------------------------------------------------------*/ 4271 + if ((struct easycap *)NULL == peasycap) { 4272 + SAY("ERROR: peasycap has become NULL\n"); 4273 + SAY("cannot call kref_put()\n"); 4274 + SAY("ending unsuccessfully: may cause memory leak\n"); 4275 + return; 4276 + } 4277 + if (!peasycap->kref.refcount.counter) { 4278 + SAY("ERROR: peasycap->kref.refcount.counter is zero " \ 4279 + "so cannot call kref_put()\n"); 4280 + SAY("ending unsuccessfully: may cause memory leak\n"); 4281 + return; 4282 + } 4283 + JOT(4, "intf[%i]: kref_put() with %i=peasycap->kref.refcount.counter\n", \ 4284 + bInterfaceNumber, (int)peasycap->kref.refcount.counter); 4285 + kref_put(&peasycap->kref, easycap_delete); 4286 + JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber); 4287 + /*---------------------------------------------------------------------------*/ 4288 + 4289 + JOT(4, "ends\n"); 4290 + return; 4291 + } 4292 + /*****************************************************************************/ 4293 + int __init 4294 + easycap_module_init(void) 4295 + { 4296 + int result; 4297 + 4298 + SAY("========easycap=======\n"); 4299 + JOT(4, "begins. %i=debug\n", easycap_debug); 4300 + SAY("version: " EASYCAP_DRIVER_VERSION "\n"); 4301 + /*---------------------------------------------------------------------------*/ 4302 + /* 4303 + * REGISTER THIS DRIVER WITH THE USB SUBSYTEM. 4304 + */ 4305 + /*---------------------------------------------------------------------------*/ 4306 + JOT(4, "registering driver easycap\n"); 4307 + 4308 + result = usb_register(&easycap_usb_driver); 4309 + if (0 != result) 4310 + SAY("ERROR: usb_register returned %i\n", result); 4311 + 4312 + JOT(4, "ends\n"); 4313 + return result; 4314 + } 4315 + /*****************************************************************************/ 4316 + void __exit 4317 + easycap_module_exit(void) 4318 + { 4319 + JOT(4, "begins\n"); 4320 + 4321 + /*---------------------------------------------------------------------------*/ 4322 + /* 4323 + * DEREGISTER THIS DRIVER WITH THE USB SUBSYTEM. 4324 + */ 4325 + /*---------------------------------------------------------------------------*/ 4326 + usb_deregister(&easycap_usb_driver); 4327 + 4328 + JOT(4, "ends\n"); 4329 + } 4330 + /*****************************************************************************/ 4331 + 4332 + module_init(easycap_module_init); 4333 + module_exit(easycap_module_exit); 4334 + 4335 + MODULE_LICENSE("GPL"); 4336 + MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>"); 4337 + MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION); 4338 + MODULE_VERSION(EASYCAP_DRIVER_VERSION); 4339 + #if defined(EASYCAP_DEBUG) 4340 + MODULE_PARM_DESC(easycap_debug, "debug: 0 (default), 1, 2,..."); 4341 + #endif /*EASYCAP_DEBUG*/ 4342 + /*****************************************************************************/
+489
drivers/staging/easycap/easycap_settings.c
··· 1 + /****************************************************************************** 2 + * * 3 + * easycap_settings.c * 4 + * * 5 + ******************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + 28 + #include "easycap.h" 29 + #include "easycap_debug.h" 30 + 31 + /*---------------------------------------------------------------------------*/ 32 + /* 33 + * THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING: 34 + * 0 => 25 fps 35 + * 1 => 30 fps 36 + */ 37 + /*---------------------------------------------------------------------------*/ 38 + struct easycap_standard easycap_standard[] = { 39 + { 40 + .mask = 0x000F & PAL_BGHIN , 41 + .v4l2_standard = { 42 + .index = PAL_BGHIN, 43 + .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G | V4L2_STD_PAL_H | \ 44 + V4L2_STD_PAL_I | V4L2_STD_PAL_N), 45 + .name = "PAL_BGHIN", 46 + .frameperiod = {1, 25}, 47 + .framelines = 625, 48 + .reserved = {0, 0, 0, 0} 49 + } 50 + }, 51 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 52 + { 53 + .mask = 0x000F & NTSC_N_443 , 54 + .v4l2_standard = { 55 + .index = NTSC_N_443, 56 + .id = V4L2_STD_UNKNOWN, 57 + .name = "NTSC_N_443", 58 + .frameperiod = {1, 25}, 59 + .framelines = 480, 60 + .reserved = {0, 0, 0, 0} 61 + } 62 + }, 63 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 64 + { 65 + .mask = 0x000F & PAL_Nc , 66 + .v4l2_standard = { 67 + .index = PAL_Nc, 68 + .id = V4L2_STD_PAL_Nc, 69 + .name = "PAL_Nc", 70 + .frameperiod = {1, 25}, 71 + .framelines = 625, 72 + .reserved = {0, 0, 0, 0} 73 + } 74 + }, 75 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 76 + { 77 + .mask = 0x000F & NTSC_N , 78 + .v4l2_standard = { 79 + .index = NTSC_N, 80 + .id = V4L2_STD_UNKNOWN, 81 + .name = "NTSC_N", 82 + .frameperiod = {1, 25}, 83 + .framelines = 525, 84 + .reserved = {0, 0, 0, 0} 85 + } 86 + }, 87 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 88 + { 89 + .mask = 0x000F & SECAM , 90 + .v4l2_standard = { 91 + .index = SECAM, 92 + .id = V4L2_STD_SECAM, 93 + .name = "SECAM", 94 + .frameperiod = {1, 25}, 95 + .framelines = 625, 96 + .reserved = {0, 0, 0, 0} 97 + } 98 + }, 99 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 100 + { 101 + .mask = 0x000F & NTSC_M , 102 + .v4l2_standard = { 103 + .index = NTSC_M, 104 + .id = V4L2_STD_NTSC_M, 105 + .name = "NTSC_M", 106 + .frameperiod = {1, 30}, 107 + .framelines = 525, 108 + .reserved = {0, 0, 0, 0} 109 + } 110 + }, 111 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 112 + { 113 + .mask = 0x000F & NTSC_M_JP , 114 + .v4l2_standard = { 115 + .index = NTSC_M_JP, 116 + .id = V4L2_STD_NTSC_M_JP, 117 + .name = "NTSC_M_JP", 118 + .frameperiod = {1, 30}, 119 + .framelines = 525, 120 + .reserved = {0, 0, 0, 0} 121 + } 122 + }, 123 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 124 + { 125 + .mask = 0x000F & PAL_60 , 126 + .v4l2_standard = { 127 + .index = PAL_60, 128 + .id = V4L2_STD_PAL_60, 129 + .name = "PAL_60", 130 + .frameperiod = {1, 30}, 131 + .framelines = 525, 132 + .reserved = {0, 0, 0, 0} 133 + } 134 + }, 135 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 136 + { 137 + .mask = 0x000F & NTSC_443 , 138 + .v4l2_standard = { 139 + .index = NTSC_443, 140 + .id = V4L2_STD_NTSC_443, 141 + .name = "NTSC_443", 142 + .frameperiod = {1, 30}, 143 + .framelines = 525, 144 + .reserved = {0, 0, 0, 0} 145 + } 146 + }, 147 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 148 + { 149 + .mask = 0x000F & PAL_M , 150 + .v4l2_standard = { 151 + .index = PAL_M, 152 + .id = V4L2_STD_PAL_M, 153 + .name = "PAL_M", 154 + .frameperiod = {1, 30}, 155 + .framelines = 525, 156 + .reserved = {0, 0, 0, 0} 157 + } 158 + }, 159 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 160 + { 161 + .mask = 0xFFFF 162 + } 163 + }; 164 + /*---------------------------------------------------------------------------*/ 165 + /* 166 + * THE 16-BIT easycap_format.mask HAS MEANING: 167 + * (least significant) BIT 0: 0 => PAL, 25 FPS; 1 => NTSC, 30 FPS 168 + * BITS 1-3: RESERVED FOR DIFFERENTIATING STANDARDS 169 + * BITS 4-7: NUMBER OF BYTES PER PIXEL 170 + * BIT 8: 0 => NATIVE BYTE ORDER; 1 => SWAPPED 171 + * BITS 9-10: RESERVED FOR OTHER BYTE PERMUTATIONS 172 + * BIT 11: 0 => UNDECIMATED; 1 => DECIMATED 173 + * BIT 12: 0 => OFFER FRAMES; 1 => OFFER FIELDS 174 + * (most significant) BITS 13-15: RESERVED FOR OTHER FIELD ORDER OPTIONS 175 + * IT FOLLOWS THAT: 176 + * bytesperpixel IS ((0x00F0 & easycap_format.mask) >> 4) 177 + * byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask)) 178 + * 179 + * decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask)) 180 + * 181 + * offerfields IS true IF (0 != (0x1000 & easycap_format.mask)) 182 + */ 183 + /*---------------------------------------------------------------------------*/ 184 + 185 + struct easycap_format easycap_format[1 + SETTINGS_MANY]; 186 + 187 + int 188 + fillin_formats(void) 189 + { 190 + int i, j, k, m, n; 191 + __u32 width, height, pixelformat, bytesperline, sizeimage; 192 + __u32 field, colorspace; 193 + __u16 mask1, mask2, mask3, mask4; 194 + char name1[32], name2[32], name3[32], name4[32]; 195 + 196 + for (i = 0, n = 0; i < STANDARD_MANY; i++) { 197 + mask1 = 0x0000; 198 + switch (i) { 199 + case PAL_BGHIN: { 200 + mask1 = PAL_BGHIN; 201 + strcpy(&name1[0], "PAL_BGHIN"); 202 + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; 203 + break; 204 + } 205 + case SECAM: { 206 + mask1 = SECAM; 207 + strcpy(&name1[0], "SECAM"); 208 + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; 209 + break; 210 + } 211 + case PAL_Nc: { 212 + mask1 = PAL_Nc; 213 + strcpy(&name1[0], "PAL_Nc"); 214 + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; 215 + break; 216 + } 217 + case PAL_60: { 218 + mask1 = PAL_60; 219 + strcpy(&name1[0], "PAL_60"); 220 + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; 221 + break; 222 + } 223 + case PAL_M: { 224 + mask1 = PAL_M; 225 + strcpy(&name1[0], "PAL_M"); 226 + colorspace = V4L2_COLORSPACE_470_SYSTEM_BG; 227 + break; 228 + } 229 + case NTSC_M: { 230 + mask1 = NTSC_M; 231 + strcpy(&name1[0], "NTSC_M"); 232 + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; 233 + break; 234 + } 235 + case NTSC_443: { 236 + mask1 = NTSC_443; 237 + strcpy(&name1[0], "NTSC_443"); 238 + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; 239 + break; 240 + } 241 + case NTSC_M_JP: { 242 + mask1 = NTSC_M_JP; 243 + strcpy(&name1[0], "NTSC_M_JP"); 244 + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; 245 + break; 246 + } 247 + case NTSC_N: { 248 + mask1 = NTSC_M; 249 + strcpy(&name1[0], "NTSC_N"); 250 + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; 251 + break; 252 + } 253 + case NTSC_N_443: { 254 + mask1 = NTSC_N_443; 255 + strcpy(&name1[0], "NTSC_N_443"); 256 + colorspace = V4L2_COLORSPACE_470_SYSTEM_M; 257 + break; 258 + } 259 + default: 260 + return -1; 261 + } 262 + 263 + for (j = 0; j < RESOLUTION_MANY; j++) { 264 + mask2 = 0x0000; 265 + switch (j) { 266 + case AT_720x576: { 267 + if (0x1 & mask1) 268 + continue; 269 + strcpy(&name2[0], "_AT_720x576"); 270 + width = 720; height = 576; break; 271 + } 272 + case AT_704x576: { 273 + if (0x1 & mask1) 274 + continue; 275 + strcpy(&name2[0], "_AT_704x576"); 276 + width = 704; height = 576; break; 277 + } 278 + case AT_640x480: { 279 + strcpy(&name2[0], "_AT_640x480"); 280 + width = 640; height = 480; break; 281 + } 282 + case AT_720x480: { 283 + if (!(0x1 & mask1)) 284 + continue; 285 + strcpy(&name2[0], "_AT_720x480"); 286 + width = 720; height = 480; break; 287 + } 288 + case AT_360x288: { 289 + if (0x1 & mask1) 290 + continue; 291 + strcpy(&name2[0], "_AT_360x288"); 292 + width = 360; height = 288; mask2 = 0x0800; break; 293 + } 294 + case AT_320x240: { 295 + strcpy(&name2[0], "_AT_320x240"); 296 + width = 320; height = 240; mask2 = 0x0800; break; 297 + } 298 + case AT_360x240: { 299 + if (!(0x1 & mask1)) 300 + continue; 301 + strcpy(&name2[0], "_AT_360x240"); 302 + width = 360; height = 240; mask2 = 0x0800; break; 303 + } 304 + default: 305 + return -2; 306 + } 307 + 308 + for (k = 0; k < PIXELFORMAT_MANY; k++) { 309 + mask3 = 0x0000; 310 + switch (k) { 311 + case FMT_UYVY: { 312 + strcpy(&name3[0], "_" STRINGIZE(FMT_UYVY)); 313 + pixelformat = V4L2_PIX_FMT_UYVY; 314 + mask3 |= (0x02 << 4); 315 + break; 316 + } 317 + case FMT_YUY2: { 318 + strcpy(&name3[0], "_" STRINGIZE(FMT_YUY2)); 319 + pixelformat = V4L2_PIX_FMT_YUYV; 320 + mask3 |= (0x02 << 4); 321 + mask3 |= 0x0100; 322 + break; 323 + } 324 + case FMT_RGB24: { 325 + strcpy(&name3[0], "_" STRINGIZE(FMT_RGB24)); 326 + pixelformat = V4L2_PIX_FMT_RGB24; 327 + mask3 |= (0x03 << 4); 328 + break; 329 + } 330 + case FMT_RGB32: { 331 + strcpy(&name3[0], "_" STRINGIZE(FMT_RGB32)); 332 + pixelformat = V4L2_PIX_FMT_RGB32; 333 + mask3 |= (0x04 << 4); 334 + break; 335 + } 336 + case FMT_BGR24: { 337 + strcpy(&name3[0], "_" STRINGIZE(FMT_BGR24)); 338 + pixelformat = V4L2_PIX_FMT_BGR24; 339 + mask3 |= (0x03 << 4); 340 + mask3 |= 0x0100; 341 + break; 342 + } 343 + case FMT_BGR32: { 344 + strcpy(&name3[0], "_" STRINGIZE(FMT_BGR32)); 345 + pixelformat = V4L2_PIX_FMT_BGR32; 346 + mask3 |= (0x04 << 4); 347 + mask3 |= 0x0100; 348 + break; 349 + } 350 + default: 351 + return -3; 352 + } 353 + bytesperline = width * ((mask3 & 0x00F0) >> 4); 354 + sizeimage = bytesperline * height; 355 + 356 + for (m = 0; m < INTERLACE_MANY; m++) { 357 + mask4 = 0x0000; 358 + switch (m) { 359 + case FIELD_NONE: { 360 + strcpy(&name4[0], "-n"); 361 + field = V4L2_FIELD_NONE; 362 + break; 363 + } 364 + case FIELD_INTERLACED: { 365 + strcpy(&name4[0], "-i"); 366 + field = V4L2_FIELD_INTERLACED; 367 + break; 368 + } 369 + case FIELD_ALTERNATE: { 370 + strcpy(&name4[0], "-a"); 371 + mask4 |= 0x1000; 372 + field = V4L2_FIELD_ALTERNATE; 373 + break; 374 + } 375 + default: 376 + return -4; 377 + } 378 + if (SETTINGS_MANY <= n) 379 + return -5; 380 + strcpy(&easycap_format[n].name[0], &name1[0]); 381 + strcat(&easycap_format[n].name[0], &name2[0]); 382 + strcat(&easycap_format[n].name[0], &name3[0]); 383 + strcat(&easycap_format[n].name[0], &name4[0]); 384 + easycap_format[n].mask = \ 385 + mask1 | mask2 | mask3 | mask4; 386 + easycap_format[n].v4l2_format\ 387 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 388 + easycap_format[n].v4l2_format\ 389 + .fmt.pix.width = width; 390 + easycap_format[n].v4l2_format\ 391 + .fmt.pix.height = height; 392 + easycap_format[n].v4l2_format\ 393 + .fmt.pix.pixelformat = pixelformat; 394 + easycap_format[n].v4l2_format\ 395 + .fmt.pix.field = field; 396 + easycap_format[n].v4l2_format\ 397 + .fmt.pix.bytesperline = bytesperline; 398 + easycap_format[n].v4l2_format\ 399 + .fmt.pix.sizeimage = sizeimage; 400 + easycap_format[n].v4l2_format\ 401 + .fmt.pix.colorspace = colorspace; 402 + easycap_format[n].v4l2_format\ 403 + .fmt.pix.priv = 0; 404 + n++; 405 + } 406 + } 407 + } 408 + } 409 + if ((1 + SETTINGS_MANY) <= n) 410 + return -6; 411 + easycap_format[n].mask = 0xFFFF; 412 + return n; 413 + } 414 + /*---------------------------------------------------------------------------*/ 415 + struct v4l2_queryctrl easycap_control[] = \ 416 + {{ 417 + .id = V4L2_CID_BRIGHTNESS, 418 + .type = V4L2_CTRL_TYPE_INTEGER, 419 + .name = "Brightness", 420 + .minimum = 0, 421 + .maximum = 255, 422 + .step = 1, 423 + .default_value = SAA_0A_DEFAULT, 424 + .flags = 0, 425 + .reserved = {0, 0} 426 + }, 427 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 428 + { 429 + .id = V4L2_CID_CONTRAST, 430 + .type = V4L2_CTRL_TYPE_INTEGER, 431 + .name = "Contrast", 432 + .minimum = 0, 433 + .maximum = 255, 434 + .step = 1, 435 + .default_value = SAA_0B_DEFAULT + 128, 436 + .flags = 0, 437 + .reserved = {0, 0} 438 + }, 439 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 440 + { 441 + .id = V4L2_CID_SATURATION, 442 + .type = V4L2_CTRL_TYPE_INTEGER, 443 + .name = "Saturation", 444 + .minimum = 0, 445 + .maximum = 255, 446 + .step = 1, 447 + .default_value = SAA_0C_DEFAULT + 128, 448 + .flags = 0, 449 + .reserved = {0, 0} 450 + }, 451 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 452 + { 453 + .id = V4L2_CID_HUE, 454 + .type = V4L2_CTRL_TYPE_INTEGER, 455 + .name = "Hue", 456 + .minimum = 0, 457 + .maximum = 255, 458 + .step = 1, 459 + .default_value = SAA_0D_DEFAULT + 128, 460 + .flags = 0, 461 + .reserved = {0, 0} 462 + }, 463 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 464 + { 465 + .id = V4L2_CID_AUDIO_VOLUME, 466 + .type = V4L2_CTRL_TYPE_INTEGER, 467 + .name = "Volume", 468 + .minimum = 0, 469 + .maximum = 31, 470 + .step = 1, 471 + .default_value = 16, 472 + .flags = 0, 473 + .reserved = {0, 0} 474 + }, 475 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 476 + { 477 + .id = V4L2_CID_AUDIO_MUTE, 478 + .type = V4L2_CTRL_TYPE_BOOLEAN, 479 + .name = "Mute", 480 + .default_value = true, 481 + .flags = 0, 482 + .reserved = {0, 0} 483 + }, 484 + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 485 + { 486 + .id = 0xFFFFFFFF 487 + } 488 + }; 489 + /*****************************************************************************/
+973
drivers/staging/easycap/easycap_sound.c
··· 1 + /****************************************************************************** 2 + * * 3 + * easycap_sound.c * 4 + * * 5 + * Audio driver for EasyCAP USB2.0 Video Capture Device DC60 * 6 + * * 7 + * * 8 + ******************************************************************************/ 9 + /* 10 + * 11 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 12 + * 13 + * 14 + * This is free software; you can redistribute it and/or modify 15 + * it under the terms of the GNU General Public License as published by 16 + * the Free Software Foundation; either version 2 of the License, or 17 + * (at your option) any later version. 18 + * 19 + * The software is distributed in the hope that it will be useful, 20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 + * GNU General Public License for more details. 23 + * 24 + * You should have received a copy of the GNU General Public License 25 + * along with this software; if not, write to the Free Software 26 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 27 + * 28 + */ 29 + /*****************************************************************************/ 30 + 31 + #include "easycap.h" 32 + #include "easycap_debug.h" 33 + #include "easycap_sound.h" 34 + 35 + /*****************************************************************************/ 36 + /*---------------------------------------------------------------------------*/ 37 + /* 38 + * ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE AUDIO BUFFERS 39 + * PROVIDED peasycap->audio_idle IS ZER0. REGARDLESS OF THIS BEING TRUE, 40 + * IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO. 41 + */ 42 + /*---------------------------------------------------------------------------*/ 43 + void 44 + easysnd_complete(struct urb *purb) 45 + { 46 + static int mt; 47 + struct easycap *peasycap; 48 + struct data_buffer *paudio_buffer; 49 + char errbuf[16]; 50 + __u8 *p1, *p2; 51 + __s16 s16; 52 + int i, j, more, much, leap, rc; 53 + 54 + JOT(16, "\n"); 55 + 56 + if (NULL == purb) { 57 + SAY("ERROR: purb is NULL\n"); 58 + return; 59 + } 60 + peasycap = purb->context; 61 + if (NULL == peasycap) { 62 + SAY("ERROR: peasycap is NULL\n"); 63 + return; 64 + } 65 + much = 0; 66 + 67 + 68 + if (peasycap->audio_idle) { 69 + JOT(16, "%i=audio_idle %i=audio_isoc_streaming\n", \ 70 + peasycap->audio_idle, peasycap->audio_isoc_streaming); 71 + if (peasycap->audio_isoc_streaming) { 72 + rc = usb_submit_urb(purb, GFP_ATOMIC); 73 + if (0 != rc) { 74 + SAY("ERROR: while %i=audio_idle, " \ 75 + "usb_submit_urb() failed with rc:\n", \ 76 + peasycap->audio_idle); 77 + switch (rc) { 78 + case -ENOMEM: { 79 + SAY("ENOMEM\n"); break; 80 + } 81 + case -ENODEV: { 82 + SAY("ENODEV\n"); break; 83 + } 84 + case -ENXIO: { 85 + SAY("ENXIO\n"); break; 86 + } 87 + case -EINVAL: { 88 + SAY("EINVAL\n"); break; 89 + } 90 + case -EAGAIN: { 91 + SAY("EAGAIN\n"); break; 92 + } 93 + case -EFBIG: { 94 + SAY("EFBIG\n"); break; 95 + } 96 + case -EPIPE: { 97 + SAY("EPIPE\n"); break; 98 + } 99 + case -EMSGSIZE: { 100 + SAY("EMSGSIZE\n"); break; 101 + } 102 + default: { 103 + SAY("0x%08X\n", rc); break; 104 + } 105 + } 106 + } 107 + } 108 + return; 109 + } 110 + /*---------------------------------------------------------------------------*/ 111 + if (purb->status) { 112 + if (-ESHUTDOWN == purb->status) { 113 + JOT(16, "immediate return because -ESHUTDOWN=purb->status\n"); 114 + return; 115 + } 116 + SAY("ERROR: non-zero urb status:\n"); 117 + switch (purb->status) { 118 + case -EINPROGRESS: { 119 + SAY("-EINPROGRESS\n"); break; 120 + } 121 + case -ENOSR: { 122 + SAY("-ENOSR\n"); break; 123 + } 124 + case -EPIPE: { 125 + SAY("-EPIPE\n"); break; 126 + } 127 + case -EOVERFLOW: { 128 + SAY("-EOVERFLOW\n"); break; 129 + } 130 + case -EPROTO: { 131 + SAY("-EPROTO\n"); break; 132 + } 133 + case -EILSEQ: { 134 + SAY("-EILSEQ\n"); break; 135 + } 136 + case -ETIMEDOUT: { 137 + SAY("-ETIMEDOUT\n"); break; 138 + } 139 + case -EMSGSIZE: { 140 + SAY("-EMSGSIZE\n"); break; 141 + } 142 + case -EOPNOTSUPP: { 143 + SAY("-EOPNOTSUPP\n"); break; 144 + } 145 + case -EPFNOSUPPORT: { 146 + SAY("-EPFNOSUPPORT\n"); break; 147 + } 148 + case -EAFNOSUPPORT: { 149 + SAY("-EAFNOSUPPORT\n"); break; 150 + } 151 + case -EADDRINUSE: { 152 + SAY("-EADDRINUSE\n"); break; 153 + } 154 + case -EADDRNOTAVAIL: { 155 + SAY("-EADDRNOTAVAIL\n"); break; 156 + } 157 + case -ENOBUFS: { 158 + SAY("-ENOBUFS\n"); break; 159 + } 160 + case -EISCONN: { 161 + SAY("-EISCONN\n"); break; 162 + } 163 + case -ENOTCONN: { 164 + SAY("-ENOTCONN\n"); break; 165 + } 166 + case -ESHUTDOWN: { 167 + SAY("-ESHUTDOWN\n"); break; 168 + } 169 + case -ENOENT: { 170 + SAY("-ENOENT\n"); break; 171 + } 172 + case -ECONNRESET: { 173 + SAY("-ECONNRESET\n"); break; 174 + } 175 + default: { 176 + SAY("unknown error code 0x%08X\n", purb->status); break; 177 + } 178 + } 179 + /*---------------------------------------------------------------------------*/ 180 + /* 181 + * RESUBMIT THIS URB AFTER AN ERROR 182 + * 183 + * (THIS IS DUPLICATE CODE TO REDUCE INDENTATION OF THE NO-ERROR PATH) 184 + */ 185 + /*---------------------------------------------------------------------------*/ 186 + if (peasycap->audio_isoc_streaming) { 187 + rc = usb_submit_urb(purb, GFP_ATOMIC); 188 + if (0 != rc) { 189 + SAY("ERROR: while %i=audio_idle, usb_submit_urb() " 190 + "failed with rc:\n", peasycap->audio_idle); 191 + switch (rc) { 192 + case -ENOMEM: { 193 + SAY("ENOMEM\n"); break; 194 + } 195 + case -ENODEV: { 196 + SAY("ENODEV\n"); break; 197 + } 198 + case -ENXIO: { 199 + SAY("ENXIO\n"); break; 200 + } 201 + case -EINVAL: { 202 + SAY("EINVAL\n"); break; 203 + } 204 + case -EAGAIN: { 205 + SAY("EAGAIN\n"); break; 206 + } 207 + case -EFBIG: { 208 + SAY("EFBIG\n"); break; 209 + } 210 + case -EPIPE: { 211 + SAY("EPIPE\n"); break; 212 + } 213 + case -EMSGSIZE: { 214 + SAY("EMSGSIZE\n"); break; 215 + } 216 + default: { 217 + SAY("0x%08X\n", rc); break; 218 + } 219 + } 220 + } 221 + } 222 + return; 223 + } 224 + /*---------------------------------------------------------------------------*/ 225 + /* 226 + * PROCEED HERE WHEN NO ERROR 227 + */ 228 + /*---------------------------------------------------------------------------*/ 229 + for (i = 0; i < purb->number_of_packets; i++) { 230 + switch (purb->iso_frame_desc[i].status) { 231 + case 0: { 232 + strcpy(&errbuf[0], "OK"); break; 233 + } 234 + case -ENOENT: { 235 + strcpy(&errbuf[0], "-ENOENT"); break; 236 + } 237 + case -EINPROGRESS: { 238 + strcpy(&errbuf[0], "-EINPROGRESS"); break; 239 + } 240 + case -EPROTO: { 241 + strcpy(&errbuf[0], "-EPROTO"); break; 242 + } 243 + case -EILSEQ: { 244 + strcpy(&errbuf[0], "-EILSEQ"); break; 245 + } 246 + case -ETIME: { 247 + strcpy(&errbuf[0], "-ETIME"); break; 248 + } 249 + case -ETIMEDOUT: { 250 + strcpy(&errbuf[0], "-ETIMEDOUT"); break; 251 + } 252 + case -EPIPE: { 253 + strcpy(&errbuf[0], "-EPIPE"); break; 254 + } 255 + case -ECOMM: { 256 + strcpy(&errbuf[0], "-ECOMM"); break; 257 + } 258 + case -ENOSR: { 259 + strcpy(&errbuf[0], "-ENOSR"); break; 260 + } 261 + case -EOVERFLOW: { 262 + strcpy(&errbuf[0], "-EOVERFLOW"); break; 263 + } 264 + case -EREMOTEIO: { 265 + strcpy(&errbuf[0], "-EREMOTEIO"); break; 266 + } 267 + case -ENODEV: { 268 + strcpy(&errbuf[0], "-ENODEV"); break; 269 + } 270 + case -EXDEV: { 271 + strcpy(&errbuf[0], "-EXDEV"); break; 272 + } 273 + case -EINVAL: { 274 + strcpy(&errbuf[0], "-EINVAL"); break; 275 + } 276 + case -ECONNRESET: { 277 + strcpy(&errbuf[0], "-ECONNRESET"); break; 278 + } 279 + case -ESHUTDOWN: { 280 + strcpy(&errbuf[0], "-ESHUTDOWN"); break; 281 + } 282 + default: { 283 + strcpy(&errbuf[0], "UNKNOWN"); break; 284 + } 285 + } 286 + if ((!purb->iso_frame_desc[i].status) && 0) { 287 + JOT(16, "frame[%2i]: %i=status{=%16s} " \ 288 + "%5i=actual " \ 289 + "%5i=length " \ 290 + "%3i=offset\n", \ 291 + i, purb->iso_frame_desc[i].status, &errbuf[0], 292 + purb->iso_frame_desc[i].actual_length, 293 + purb->iso_frame_desc[i].length, 294 + purb->iso_frame_desc[i].offset); 295 + } 296 + if (!purb->iso_frame_desc[i].status) { 297 + more = purb->iso_frame_desc[i].actual_length; 298 + 299 + #if defined(TESTTONE) 300 + if (!more) 301 + more = purb->iso_frame_desc[i].length; 302 + #endif 303 + 304 + if (!more) 305 + mt++; 306 + else { 307 + if (mt) { 308 + JOT(16, "%4i empty audio urb frames\n", mt); 309 + mt = 0; 310 + } 311 + 312 + p1 = (__u8 *)(purb->transfer_buffer + \ 313 + purb->iso_frame_desc[i].offset); 314 + 315 + leap = 0; 316 + p1 += leap; 317 + more -= leap; 318 + /*---------------------------------------------------------------------------*/ 319 + /* 320 + * COPY more BYTES FROM ISOC BUFFER TO AUDIO BUFFER, 321 + * CONVERTING 8-BIT SAMPLES TO 16-BIT SIGNED LITTLE-ENDED SAMPLES IF NECESSARY 322 + */ 323 + /*---------------------------------------------------------------------------*/ 324 + while (more) { 325 + if (0 > more) { 326 + SAY("easysnd_complete: MISTAKE: " \ 327 + "more is negative\n"); 328 + return; 329 + } 330 + if (audio_buffer_page_many <= \ 331 + peasycap->audio_fill) { 332 + SAY("ERROR: bad " \ 333 + "peasycap->audio_fill\n"); 334 + return; 335 + } 336 + 337 + paudio_buffer = &peasycap->audio_buffer\ 338 + [peasycap->audio_fill]; 339 + if (PAGE_SIZE < (paudio_buffer->pto - \ 340 + paudio_buffer->pgo)) { 341 + SAY("ERROR: bad paudio_buffer->pto\n"); 342 + return; 343 + } 344 + if (PAGE_SIZE == (paudio_buffer->pto - \ 345 + paudio_buffer->pgo)) { 346 + 347 + #if defined(TESTTONE) 348 + easysnd_testtone(peasycap, \ 349 + peasycap->audio_fill); 350 + #endif /*TESTTONE*/ 351 + 352 + paudio_buffer->pto = \ 353 + paudio_buffer->pgo; 354 + (peasycap->audio_fill)++; 355 + if (audio_buffer_page_many <= \ 356 + peasycap->audio_fill) 357 + peasycap->audio_fill = 0; 358 + 359 + JOT(12, "bumped peasycap->" \ 360 + "audio_fill to %i\n", \ 361 + peasycap->audio_fill); 362 + 363 + paudio_buffer = &peasycap->\ 364 + audio_buffer\ 365 + [peasycap->audio_fill]; 366 + paudio_buffer->pto = \ 367 + paudio_buffer->pgo; 368 + 369 + if (!(peasycap->audio_fill % \ 370 + audio_pages_per_fragment)) { 371 + JOT(12, "wakeup call on wq_" \ 372 + "audio, %i=frag reading %i" \ 373 + "=fragment fill\n", \ 374 + (peasycap->audio_read / \ 375 + audio_pages_per_fragment), \ 376 + (peasycap->audio_fill / \ 377 + audio_pages_per_fragment)); 378 + wake_up_interruptible\ 379 + (&(peasycap->wq_audio)); 380 + } 381 + } 382 + 383 + much = PAGE_SIZE - (int)(paudio_buffer->pto -\ 384 + paudio_buffer->pgo); 385 + if (much % 2) 386 + JOT(8, "MISTAKE? much is odd\n"); 387 + 388 + if (false == peasycap->microphone) { 389 + if (much > more) 390 + much = more; 391 + 392 + memcpy(paudio_buffer->pto, p1, much); 393 + p1 += much; 394 + more -= much; 395 + } else { 396 + if (much > (2 * more)) 397 + much = 2 * more; 398 + p2 = (__u8 *)paudio_buffer->pto; 399 + 400 + for (j = 0; j < (much / 2); j++) { 401 + s16 = ((int) *p1) - 128; 402 + *p2 = (0xFF00 & s16) >> 8; 403 + *(p2 + 1) = (0x00FF & s16); 404 + p1++; p2 += 2; 405 + more--; 406 + } 407 + } 408 + (paudio_buffer->pto) += much; 409 + } 410 + } 411 + } else { 412 + JOT(12, "discarding audio samples because " \ 413 + "%i=purb->iso_frame_desc[i].status\n", \ 414 + purb->iso_frame_desc[i].status); 415 + } 416 + } 417 + /*---------------------------------------------------------------------------*/ 418 + /* 419 + * RESUBMIT THIS URB AFTER NO ERROR 420 + */ 421 + /*---------------------------------------------------------------------------*/ 422 + if (peasycap->audio_isoc_streaming) { 423 + rc = usb_submit_urb(purb, GFP_ATOMIC); 424 + if (0 != rc) { 425 + SAY("ERROR: while %i=audio_idle, usb_submit_urb() failed " \ 426 + "with rc:\n", peasycap->audio_idle); 427 + switch (rc) { 428 + case -ENOMEM: { 429 + SAY("ENOMEM\n"); break; 430 + } 431 + case -ENODEV: { 432 + SAY("ENODEV\n"); break; 433 + } 434 + case -ENXIO: { 435 + SAY("ENXIO\n"); break; 436 + } 437 + case -EINVAL: { 438 + SAY("EINVAL\n"); break; 439 + } 440 + case -EAGAIN: { 441 + SAY("EAGAIN\n"); break; 442 + } 443 + case -EFBIG: { 444 + SAY("EFBIG\n"); break; 445 + } 446 + case -EPIPE: { 447 + SAY("EPIPE\n"); break; 448 + } 449 + case -EMSGSIZE: { 450 + SAY("EMSGSIZE\n"); break; 451 + } 452 + default: { 453 + SAY("0x%08X\n", rc); break; 454 + } 455 + } 456 + } 457 + } 458 + return; 459 + } 460 + /*****************************************************************************/ 461 + /*---------------------------------------------------------------------------*/ 462 + /* 463 + * THE AUDIO URBS ARE SUBMITTED AT THIS EARLY STAGE SO THAT IT IS POSSIBLE TO 464 + * STREAM FROM /dev/easysnd1 WITH SIMPLE PROGRAMS SUCH AS cat WHICH DO NOT 465 + * HAVE AN IOCTL INTERFACE. THE VIDEO URBS, BY CONTRAST, MUST BE SUBMITTED 466 + * MUCH LATER: SEE COMMENTS IN FILE easycap_main.c. 467 + */ 468 + /*---------------------------------------------------------------------------*/ 469 + int 470 + easysnd_open(struct inode *inode, struct file *file) 471 + { 472 + struct usb_interface *pusb_interface; 473 + struct easycap *peasycap; 474 + int subminor, rc; 475 + 476 + JOT(4, "begins.\n"); 477 + 478 + subminor = iminor(inode); 479 + 480 + pusb_interface = usb_find_interface(&easycap_usb_driver, subminor); 481 + if (NULL == pusb_interface) { 482 + SAY("ERROR: pusb_interface is NULL\n"); 483 + SAY("ending unsuccessfully\n"); 484 + return -1; 485 + } 486 + peasycap = usb_get_intfdata(pusb_interface); 487 + if (NULL == peasycap) { 488 + SAY("ERROR: peasycap is NULL\n"); 489 + SAY("ending unsuccessfully\n"); 490 + return -1; 491 + } 492 + 493 + file->private_data = peasycap; 494 + 495 + /*---------------------------------------------------------------------------*/ 496 + /* 497 + * INITIALIZATION. 498 + */ 499 + /*---------------------------------------------------------------------------*/ 500 + JOT(4, "starting initialization\n"); 501 + 502 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 503 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 504 + return -EFAULT; 505 + } else { 506 + JOT(16, "0x%08lX=peasycap->pusb_device\n", \ 507 + (long int)peasycap->pusb_device); 508 + } 509 + 510 + rc = audio_setup(peasycap); 511 + if (0 <= rc) 512 + JOT(8, "audio_setup() returned %i\n", rc); 513 + else 514 + JOT(8, "easysnd open(): ERROR: audio_setup() returned %i\n", rc); 515 + 516 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 517 + SAY("ERROR: peasycap->pusb_device has become NULL\n"); 518 + return -EFAULT; 519 + } 520 + rc = adjust_volume(peasycap, -8192); 521 + if (0 != rc) { 522 + SAY("ERROR: adjust_volume(default) returned %i\n", rc); 523 + return -EFAULT; 524 + } 525 + /*---------------------------------------------------------------------------*/ 526 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 527 + SAY("ERROR: peasycap->pusb_device has become NULL\n"); 528 + return -EFAULT; 529 + } 530 + rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface, \ 531 + peasycap->audio_altsetting_on); 532 + JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface, \ 533 + peasycap->audio_altsetting_on, rc); 534 + 535 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 536 + SAY("ERROR: peasycap->pusb_device has become NULL\n"); 537 + return -EFAULT; 538 + } 539 + rc = wakeup_device(peasycap->pusb_device); 540 + if (0 == rc) 541 + JOT(8, "wakeup_device() returned %i\n", rc); 542 + else 543 + JOT(8, "easysnd open(): ERROR: wakeup_device() returned %i\n", rc); 544 + 545 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 546 + SAY("ERROR: peasycap->pusb_device has become NULL\n"); 547 + return -EFAULT; 548 + } 549 + submit_audio_urbs(peasycap); 550 + peasycap->audio_idle = 0; 551 + 552 + peasycap->timeval1.tv_sec = 0; 553 + peasycap->timeval1.tv_usec = 0; 554 + 555 + JOT(4, "finished initialization\n"); 556 + return 0; 557 + } 558 + /*****************************************************************************/ 559 + int 560 + easysnd_release(struct inode *inode, struct file *file) 561 + { 562 + struct easycap *peasycap; 563 + 564 + JOT(4, "begins\n"); 565 + 566 + peasycap = (struct easycap *)file->private_data; 567 + if (NULL == peasycap) { 568 + SAY("ERROR: peasycap is NULL.\n"); 569 + return -EFAULT; 570 + } 571 + if (0 != kill_audio_urbs(peasycap)) { 572 + SAY("ERROR: kill_audio_urbs() failed\n"); 573 + return -EFAULT; 574 + } 575 + JOT(4, "ending successfully\n"); 576 + return 0; 577 + } 578 + /*****************************************************************************/ 579 + ssize_t 580 + easysnd_read(struct file *file, char __user *puserspacebuffer, \ 581 + size_t kount, loff_t *poff) 582 + { 583 + struct timeval timeval; 584 + static struct timeval timeval1; 585 + static long long int audio_bytes, above, below, mean; 586 + struct signed_div_result sdr; 587 + unsigned char *p0; 588 + long int kount1, more, rc, l0, lm; 589 + int fragment; 590 + struct easycap *peasycap; 591 + struct data_buffer *pdata_buffer; 592 + size_t szret; 593 + 594 + /*---------------------------------------------------------------------------*/ 595 + /* 596 + * DO A BLOCKING READ TO TRANSFER DATA TO USER SPACE. 597 + * 598 + ****************************************************************************** 599 + ***** N.B. IF THIS FUNCTION RETURNS 0, NOTHING IS SEEN IN USER SPACE. ****** 600 + ***** THIS CONDITION SIGNIFIES END-OF-FILE. ****** 601 + ****************************************************************************** 602 + */ 603 + /*---------------------------------------------------------------------------*/ 604 + 605 + JOT(8, "===== easysnd_read(): kount=%i, *poff=%i\n", (int)kount, (int)(*poff)); 606 + 607 + peasycap = (struct easycap *)(file->private_data); 608 + if (NULL == peasycap) { 609 + SAY("ERROR in easysnd_read(): peasycap is NULL\n"); 610 + return -EFAULT; 611 + } 612 + /*---------------------------------------------------------------------------*/ 613 + if ((0 > peasycap->audio_read) || \ 614 + (audio_buffer_page_many <= peasycap->audio_read)) { 615 + SAY("ERROR: peasycap->audio_read out of range\n"); 616 + return -EFAULT; 617 + } 618 + pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; 619 + if ((struct data_buffer *)NULL == pdata_buffer) { 620 + SAY("ERROR: pdata_buffer is NULL\n"); 621 + return -EFAULT; 622 + } 623 + JOT(12, "before wait, %i=frag read %i=frag fill\n", \ 624 + (peasycap->audio_read / audio_pages_per_fragment), \ 625 + (peasycap->audio_fill / audio_pages_per_fragment)); 626 + fragment = (peasycap->audio_read / audio_pages_per_fragment); 627 + while ((fragment == (peasycap->audio_fill / audio_pages_per_fragment)) || \ 628 + (0 == (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))) { 629 + if (file->f_flags & O_NONBLOCK) { 630 + JOT(16, "returning -EAGAIN as instructed\n"); 631 + return -EAGAIN; 632 + } 633 + rc = wait_event_interruptible(peasycap->wq_audio, \ 634 + (peasycap->audio_idle || peasycap->audio_eof || \ 635 + ((fragment != (peasycap->audio_fill / \ 636 + audio_pages_per_fragment)) && \ 637 + (0 < (PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo)))))); 638 + if (0 != rc) { 639 + SAY("aborted by signal\n"); 640 + return -ERESTARTSYS; 641 + } 642 + if (peasycap->audio_eof) { 643 + JOT(8, "returning 0 because %i=audio_eof\n", \ 644 + peasycap->audio_eof); 645 + kill_audio_urbs(peasycap); 646 + msleep(500); 647 + return 0; 648 + } 649 + if (peasycap->audio_idle) { 650 + JOT(16, "returning 0 because %i=audio_idle\n", \ 651 + peasycap->audio_idle); 652 + return 0; 653 + } 654 + if (!peasycap->audio_isoc_streaming) { 655 + JOT(16, "returning 0 because audio urbs not streaming\n"); 656 + return 0; 657 + } 658 + } 659 + JOT(12, "after wait, %i=frag read %i=frag fill\n", \ 660 + (peasycap->audio_read / audio_pages_per_fragment), \ 661 + (peasycap->audio_fill / audio_pages_per_fragment)); 662 + szret = (size_t)0; 663 + while (fragment == (peasycap->audio_read / audio_pages_per_fragment)) { 664 + if (NULL == pdata_buffer->pgo) { 665 + SAY("ERROR: pdata_buffer->pgo is NULL\n"); 666 + return -EFAULT; 667 + } 668 + if (NULL == pdata_buffer->pto) { 669 + SAY("ERROR: pdata_buffer->pto is NULL\n"); 670 + return -EFAULT; 671 + } 672 + kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); 673 + if (0 > kount1) { 674 + SAY("easysnd_read: MISTAKE: kount1 is negative\n"); 675 + return -ERESTARTSYS; 676 + } 677 + if (!kount1) { 678 + (peasycap->audio_read)++; 679 + if (audio_buffer_page_many <= peasycap->audio_read) 680 + peasycap->audio_read = 0; 681 + JOT(12, "bumped peasycap->audio_read to %i\n", \ 682 + peasycap->audio_read); 683 + 684 + if (fragment != (peasycap->audio_read / \ 685 + audio_pages_per_fragment)) 686 + break; 687 + 688 + if ((0 > peasycap->audio_read) || \ 689 + (audio_buffer_page_many <= peasycap->audio_read)) { 690 + SAY("ERROR: peasycap->audio_read out of range\n"); 691 + return -EFAULT; 692 + } 693 + pdata_buffer = &peasycap->audio_buffer[peasycap->audio_read]; 694 + if ((struct data_buffer *)NULL == pdata_buffer) { 695 + SAY("ERROR: pdata_buffer is NULL\n"); 696 + return -EFAULT; 697 + } 698 + if (NULL == pdata_buffer->pgo) { 699 + SAY("ERROR: pdata_buffer->pgo is NULL\n"); 700 + return -EFAULT; 701 + } 702 + if (NULL == pdata_buffer->pto) { 703 + SAY("ERROR: pdata_buffer->pto is NULL\n"); 704 + return -EFAULT; 705 + } 706 + kount1 = PAGE_SIZE - (pdata_buffer->pto - pdata_buffer->pgo); 707 + } 708 + JOT(12, "ready to send %li bytes\n", (long int) kount1); 709 + JOT(12, "still to send %li bytes\n", (long int) kount); 710 + more = kount1; 711 + if (more > kount) 712 + more = kount; 713 + JOT(12, "agreed to send %li bytes from page %i\n", \ 714 + more, peasycap->audio_read); 715 + if (!more) 716 + break; 717 + 718 + /*---------------------------------------------------------------------------*/ 719 + /* 720 + * ACCUMULATE DYNAMIC-RANGE INFORMATION 721 + */ 722 + /*---------------------------------------------------------------------------*/ 723 + p0 = (unsigned char *)pdata_buffer->pgo; l0 = 0; lm = more/2; 724 + while (l0 < lm) { 725 + SUMMER(p0, &peasycap->audio_sample, &peasycap->audio_niveau, \ 726 + &peasycap->audio_square); l0++; p0 += 2; 727 + } 728 + /*---------------------------------------------------------------------------*/ 729 + rc = copy_to_user(puserspacebuffer, pdata_buffer->pto, more); 730 + if (0 != rc) { 731 + SAY("ERROR: copy_to_user() returned %li\n", rc); 732 + return -EFAULT; 733 + } 734 + *poff += (loff_t)more; 735 + szret += (size_t)more; 736 + pdata_buffer->pto += more; 737 + puserspacebuffer += more; 738 + kount -= (size_t)more; 739 + } 740 + JOT(12, "after read, %i=frag read %i=frag fill\n", \ 741 + (peasycap->audio_read / audio_pages_per_fragment), \ 742 + (peasycap->audio_fill / audio_pages_per_fragment)); 743 + if (kount < 0) { 744 + SAY("MISTAKE: %li=kount %li=szret\n", \ 745 + (long int)kount, (long int)szret); 746 + } 747 + /*---------------------------------------------------------------------------*/ 748 + /* 749 + * CALCULATE DYNAMIC RANGE FOR (VAPOURWARE) AUTOMATIC VOLUME CONTROL 750 + */ 751 + /*---------------------------------------------------------------------------*/ 752 + if (peasycap->audio_sample) { 753 + below = peasycap->audio_sample; 754 + above = peasycap->audio_square; 755 + sdr = signed_div(above, below); 756 + above = sdr.quotient; 757 + mean = peasycap->audio_niveau; 758 + sdr = signed_div(mean, peasycap->audio_sample); 759 + 760 + JOT(12, "%8lli=mean %8lli=meansquare after %lli samples, =>\n", \ 761 + sdr.quotient, above, peasycap->audio_sample); 762 + 763 + sdr = signed_div(above, 32768); 764 + JOT(8, "audio dynamic range is roughly %lli\n", sdr.quotient); 765 + } 766 + /*---------------------------------------------------------------------------*/ 767 + /* 768 + * UPDATE THE AUDIO CLOCK 769 + */ 770 + /*---------------------------------------------------------------------------*/ 771 + do_gettimeofday(&timeval); 772 + if (!peasycap->timeval1.tv_sec) { 773 + audio_bytes = 0; 774 + timeval1 = timeval; 775 + 776 + if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) 777 + return -ERESTARTSYS; 778 + peasycap->timeval1 = timeval1; 779 + mutex_unlock(&(peasycap->mutex_timeval1)); 780 + sdr.quotient = 192000; 781 + } else { 782 + audio_bytes += (long long int) szret; 783 + below = ((long long int)(1000000)) * \ 784 + ((long long int)(timeval.tv_sec - timeval1.tv_sec)) + \ 785 + (long long int)(timeval.tv_usec - timeval1.tv_usec); 786 + above = 1000000 * ((long long int) audio_bytes); 787 + 788 + if (below) 789 + sdr = signed_div(above, below); 790 + else 791 + sdr.quotient = 192000; 792 + } 793 + JOT(8, "audio streaming at %lli bytes/second\n", sdr.quotient); 794 + if (mutex_lock_interruptible(&(peasycap->mutex_timeval1))) 795 + return -ERESTARTSYS; 796 + peasycap->dnbydt = sdr.quotient; 797 + mutex_unlock(&(peasycap->mutex_timeval1)); 798 + 799 + JOT(8, "returning %li\n", (long int)szret); 800 + return szret; 801 + } 802 + /*****************************************************************************/ 803 + /*---------------------------------------------------------------------------*/ 804 + /* 805 + * SUBMIT ALL AUDIO URBS. 806 + */ 807 + /*---------------------------------------------------------------------------*/ 808 + int 809 + submit_audio_urbs(struct easycap *peasycap) 810 + { 811 + struct data_urb *pdata_urb; 812 + struct urb *purb; 813 + struct list_head *plist_head; 814 + int j, isbad, m, rc; 815 + int isbuf; 816 + 817 + if ((struct list_head *)NULL == peasycap->purb_audio_head) { 818 + SAY("ERROR: peasycap->urb_audio_head uninitialized\n"); 819 + return -EFAULT; 820 + } 821 + if ((struct usb_device *)NULL == peasycap->pusb_device) { 822 + SAY("ERROR: peasycap->pusb_device is NULL\n"); 823 + return -EFAULT; 824 + } 825 + if (!peasycap->audio_isoc_streaming) { 826 + JOT(4, "initial submission of all audio urbs\n"); 827 + rc = usb_set_interface(peasycap->pusb_device, 828 + peasycap->audio_interface, \ 829 + peasycap->audio_altsetting_on); 830 + JOT(8, "usb_set_interface(.,%i,%i) returned %i\n", \ 831 + peasycap->audio_interface, \ 832 + peasycap->audio_altsetting_on, rc); 833 + 834 + isbad = 0; m = 0; 835 + list_for_each(plist_head, (peasycap->purb_audio_head)) { 836 + pdata_urb = list_entry(plist_head, struct data_urb, list_head); 837 + if (NULL != pdata_urb) { 838 + purb = pdata_urb->purb; 839 + if (NULL != purb) { 840 + isbuf = pdata_urb->isbuf; 841 + 842 + purb->interval = 1; 843 + purb->dev = peasycap->pusb_device; 844 + purb->pipe = \ 845 + usb_rcvisocpipe(peasycap->pusb_device,\ 846 + peasycap->audio_endpointnumber); 847 + purb->transfer_flags = URB_ISO_ASAP; 848 + purb->transfer_buffer = \ 849 + peasycap->audio_isoc_buffer[isbuf].pgo; 850 + purb->transfer_buffer_length = \ 851 + peasycap->audio_isoc_buffer_size; 852 + purb->complete = easysnd_complete; 853 + purb->context = peasycap; 854 + purb->start_frame = 0; 855 + purb->number_of_packets = \ 856 + peasycap->audio_isoc_framesperdesc; 857 + for (j = 0; j < peasycap->\ 858 + audio_isoc_framesperdesc; \ 859 + j++) { 860 + purb->iso_frame_desc[j].offset = j * \ 861 + peasycap->\ 862 + audio_isoc_maxframesize; 863 + purb->iso_frame_desc[j].length = \ 864 + peasycap->\ 865 + audio_isoc_maxframesize; 866 + } 867 + 868 + rc = usb_submit_urb(purb, GFP_KERNEL); 869 + if (0 != rc) { 870 + isbad++; 871 + SAY("ERROR: usb_submit_urb() failed" \ 872 + " for urb with rc:\n"); 873 + switch (rc) { 874 + case -ENOMEM: { 875 + SAY("ENOMEM\n"); break; 876 + } 877 + case -ENODEV: { 878 + SAY("ENODEV\n"); break; 879 + } 880 + case -ENXIO: { 881 + SAY("ENXIO\n"); break; 882 + } 883 + case -EINVAL: { 884 + SAY("EINVAL\n"); break; 885 + } 886 + case -EAGAIN: { 887 + SAY("EAGAIN\n"); break; 888 + } 889 + case -EFBIG: { 890 + SAY("EFBIG\n"); break; 891 + } 892 + case -EPIPE: { 893 + SAY("EPIPE\n"); break; 894 + } 895 + case -EMSGSIZE: { 896 + SAY("EMSGSIZE\n"); break; 897 + } 898 + default: { 899 + SAY("unknown error code %i\n",\ 900 + rc); break; 901 + } 902 + } 903 + } else { 904 + m++; 905 + } 906 + } else { 907 + isbad++; 908 + } 909 + } else { 910 + isbad++; 911 + } 912 + } 913 + if (isbad) { 914 + JOT(4, "attempting cleanup instead of submitting\n"); 915 + list_for_each(plist_head, (peasycap->purb_audio_head)) { 916 + pdata_urb = list_entry(plist_head, struct data_urb, \ 917 + list_head); 918 + if (NULL != pdata_urb) { 919 + purb = pdata_urb->purb; 920 + if (NULL != purb) 921 + usb_kill_urb(purb); 922 + } 923 + } 924 + peasycap->audio_isoc_streaming = 0; 925 + } else { 926 + peasycap->audio_isoc_streaming = 1; 927 + JOT(4, "submitted %i audio urbs\n", m); 928 + } 929 + } else 930 + JOT(4, "already streaming audio urbs\n"); 931 + 932 + return 0; 933 + } 934 + /*****************************************************************************/ 935 + /*---------------------------------------------------------------------------*/ 936 + /* 937 + * KILL ALL AUDIO URBS. 938 + */ 939 + /*---------------------------------------------------------------------------*/ 940 + int 941 + kill_audio_urbs(struct easycap *peasycap) 942 + { 943 + int m; 944 + struct list_head *plist_head; 945 + struct data_urb *pdata_urb; 946 + 947 + if (peasycap->audio_isoc_streaming) { 948 + if ((struct list_head *)NULL != peasycap->purb_audio_head) { 949 + peasycap->audio_isoc_streaming = 0; 950 + JOT(4, "killing audio urbs\n"); 951 + m = 0; 952 + list_for_each(plist_head, (peasycap->purb_audio_head)) { 953 + pdata_urb = list_entry(plist_head, struct data_urb, 954 + list_head); 955 + if ((struct data_urb *)NULL != pdata_urb) { 956 + if ((struct urb *)NULL != pdata_urb->purb) { 957 + usb_kill_urb(pdata_urb->purb); 958 + m++; 959 + } 960 + } 961 + } 962 + JOT(4, "%i audio urbs killed\n", m); 963 + } else { 964 + SAY("ERROR: peasycap->purb_audio_head is NULL\n"); 965 + return -EFAULT; 966 + } 967 + } else { 968 + JOT(8, "%i=audio_isoc_streaming, no audio urbs killed\n", \ 969 + peasycap->audio_isoc_streaming); 970 + } 971 + return 0; 972 + } 973 + /*****************************************************************************/
+30
drivers/staging/easycap/easycap_sound.h
··· 1 + /***************************************************************************** 2 + * * 3 + * easycap_sound.h * 4 + * * 5 + *****************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + extern struct easycap *peasycap; 28 + extern struct usb_driver easycap_usb_driver; 29 + extern unsigned int audio_buffer_page_many; 30 + extern unsigned int audio_pages_per_fragment;
+27
drivers/staging/easycap/easycap_standard.h
··· 1 + /***************************************************************************** 2 + * * 3 + * easycap_standard.h * 4 + * * 5 + *****************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + extern struct easycap_standard easycap_standard[];
+392
drivers/staging/easycap/easycap_testcard.c
··· 1 + /****************************************************************************** 2 + * * 3 + * easycap_testcard.c * 4 + * * 5 + ******************************************************************************/ 6 + /* 7 + * 8 + * Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org> 9 + * 10 + * 11 + * This is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License as published by 13 + * the Free Software Foundation; either version 2 of the License, or 14 + * (at your option) any later version. 15 + * 16 + * The software is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * You should have received a copy of the GNU General Public License 22 + * along with this software; if not, write to the Free Software 23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 + * 25 + */ 26 + /*****************************************************************************/ 27 + 28 + #include "easycap.h" 29 + #include "easycap_debug.h" 30 + 31 + /*****************************************************************************/ 32 + #define TESTCARD_BYTESPERLINE (2 * 1440) 33 + void 34 + easycap_testcard(struct easycap *peasycap, int field_fill) 35 + { 36 + int total; 37 + int y, u, v, r, g, b; 38 + unsigned char uyvy[4]; 39 + 40 + int i1, line, k, m, n, more, much, barwidth; 41 + unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2; 42 + struct data_buffer *pfield_buffer; 43 + 44 + JOT(8, "%i=field_fill\n", field_fill); 45 + 46 + if ((TESTCARD_BYTESPERLINE / 2) < peasycap->width) { 47 + SAY("ERROR: image is too wide\n"); 48 + return; 49 + } 50 + if (peasycap->width % 16) { 51 + SAY("ERROR: indivisible image width\n"); 52 + return; 53 + } 54 + 55 + total = 0; 56 + barwidth = (2 * peasycap->width) / 8; 57 + 58 + k = field_fill; 59 + m = 0; 60 + n = 0; 61 + 62 + for (line = 0; line < (peasycap->height / 2); line++) { 63 + for (i1 = 0; i1 < 8; i1++) { 64 + r = (i1 * 256)/8; 65 + g = (i1 * 256)/8; 66 + b = (i1 * 256)/8; 67 + 68 + y = 299*r/1000 + 587*g/1000 + 114*b/1000 ; 69 + u = -147*r/1000 - 289*g/1000 + 436*b/1000 ; u = u + 128; 70 + v = 615*r/1000 - 515*g/1000 - 100*b/1000 ; v = v + 128; 71 + 72 + uyvy[0] = 0xFF & u ; 73 + uyvy[1] = 0xFF & y ; 74 + uyvy[2] = 0xFF & v ; 75 + uyvy[3] = 0xFF & y ; 76 + 77 + p1 = &bfbar[0]; 78 + while (p1 < &bfbar[barwidth]) { 79 + *p1++ = uyvy[0] ; 80 + *p1++ = uyvy[1] ; 81 + *p1++ = uyvy[2] ; 82 + *p1++ = uyvy[3] ; 83 + total += 4; 84 + } 85 + 86 + p1 = &bfbar[0]; 87 + more = barwidth; 88 + 89 + while (more) { 90 + if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) { 91 + SAY("ERROR: bad m reached\n"); 92 + return; 93 + } 94 + if (PAGE_SIZE < n) { 95 + SAY("ERROR: bad n reached\n"); return; 96 + } 97 + 98 + if (0 > more) { 99 + SAY("ERROR: internal fault\n"); 100 + return; 101 + } 102 + 103 + much = PAGE_SIZE - n; 104 + if (much > more) 105 + much = more; 106 + pfield_buffer = &peasycap->field_buffer[k][m]; 107 + p2 = pfield_buffer->pgo + n; 108 + memcpy(p2, p1, much); 109 + 110 + p1 += much; 111 + n += much; 112 + more -= much; 113 + if (PAGE_SIZE == n) { 114 + m++; 115 + n = 0; 116 + } 117 + } 118 + } 119 + } 120 + 121 + JOT(8, "%i=total\n", total); 122 + if (total != peasycap->width * peasycap->height) 123 + SAY("ERROR: wrong number of bytes written: %i\n", total); 124 + return; 125 + } 126 + /*****************************************************************************/ 127 + #if defined(EASYCAP_TESTTONE) 128 + /*----------------------------------------------------------------------------- 129 + THE tones[] ARRAY BELOW IS THE OUTPUT OF THIS PROGRAM, 130 + COMPILED gcc -o prog -lm prog.c 131 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 132 + #include <stdio.h> 133 + #include <math.h> 134 + 135 + int main(void); 136 + int 137 + main(void) 138 + { 139 + int i1, i2, last; 140 + double d1, d2; 141 + 142 + last = 1024 - 1; 143 + d1 = 10.0*3.14159265/1024.0; 144 + printf("int tones[2048] =\n{\n"); 145 + for (i1 = 0; i1 <= last; i1++) 146 + { 147 + d2 = ((double)i1) * d1; 148 + i2 = (int)(16384.0*sin(d2)); 149 + 150 + if (last != i1) 151 + { 152 + printf("%6i, ", i2); printf("%6i, ", i2); 153 + if (!((i1 + 1)%5)) printf("\n"); 154 + } 155 + else 156 + { 157 + printf("%6i, ", i2); printf("%6i\n};\n", i2); 158 + } 159 + } 160 + return(0); 161 + } 162 + -----------------------------------------------------------------------------*/ 163 + int tones[2048] = { 164 + 0, 0, 502, 502, 1004, 1004, 1505, 1505, 2005, 2005, 165 + 2503, 2503, 2998, 2998, 3491, 3491, 3980, 3980, 4466, 4466, 166 + 4948, 4948, 5424, 5424, 5896, 5896, 6362, 6362, 6822, 6822, 167 + 7276, 7276, 7723, 7723, 8162, 8162, 8594, 8594, 9018, 9018, 168 + 9434, 9434, 9840, 9840, 10237, 10237, 10625, 10625, 11002, 11002, 169 + 11370, 11370, 11726, 11726, 12072, 12072, 12406, 12406, 12728, 12728, 170 + 13038, 13038, 13337, 13337, 13622, 13622, 13895, 13895, 14155, 14155, 171 + 14401, 14401, 14634, 14634, 14853, 14853, 15058, 15058, 15249, 15249, 172 + 15426, 15426, 15588, 15588, 15735, 15735, 15868, 15868, 15985, 15985, 173 + 16088, 16088, 16175, 16175, 16248, 16248, 16305, 16305, 16346, 16346, 174 + 16372, 16372, 16383, 16383, 16379, 16379, 16359, 16359, 16323, 16323, 175 + 16272, 16272, 16206, 16206, 16125, 16125, 16028, 16028, 15917, 15917, 176 + 15790, 15790, 15649, 15649, 15492, 15492, 15322, 15322, 15136, 15136, 177 + 14937, 14937, 14723, 14723, 14496, 14496, 14255, 14255, 14001, 14001, 178 + 13733, 13733, 13452, 13452, 13159, 13159, 12854, 12854, 12536, 12536, 179 + 12207, 12207, 11866, 11866, 11513, 11513, 11150, 11150, 10777, 10777, 180 + 10393, 10393, 10000, 10000, 9597, 9597, 9185, 9185, 8765, 8765, 181 + 8336, 8336, 7900, 7900, 7456, 7456, 7005, 7005, 6547, 6547, 182 + 6083, 6083, 5614, 5614, 5139, 5139, 4659, 4659, 4175, 4175, 183 + 3687, 3687, 3196, 3196, 2701, 2701, 2204, 2204, 1705, 1705, 184 + 1205, 1205, 703, 703, 201, 201, -301, -301, -803, -803, 185 + -1305, -1305, -1805, -1805, -2304, -2304, -2801, -2801, -3294, -3294, 186 + -3785, -3785, -4272, -4272, -4756, -4756, -5234, -5234, -5708, -5708, 187 + -6176, -6176, -6639, -6639, -7095, -7095, -7545, -7545, -7988, -7988, 188 + -8423, -8423, -8850, -8850, -9268, -9268, -9679, -9679, -10079, -10079, 189 + -10471, -10471, -10853, -10853, -11224, -11224, -11585, -11585, -11935, -11935, 190 + -12273, -12273, -12600, -12600, -12916, -12916, -13219, -13219, -13510, -13510, 191 + -13788, -13788, -14053, -14053, -14304, -14304, -14543, -14543, -14767, -14767, 192 + -14978, -14978, -15175, -15175, -15357, -15357, -15525, -15525, -15678, -15678, 193 + -15817, -15817, -15940, -15940, -16049, -16049, -16142, -16142, -16221, -16221, 194 + -16284, -16284, -16331, -16331, -16364, -16364, -16381, -16381, -16382, -16382, 195 + -16368, -16368, -16339, -16339, -16294, -16294, -16234, -16234, -16159, -16159, 196 + -16069, -16069, -15963, -15963, -15842, -15842, -15707, -15707, -15557, -15557, 197 + -15392, -15392, -15212, -15212, -15018, -15018, -14810, -14810, -14589, -14589, 198 + -14353, -14353, -14104, -14104, -13842, -13842, -13566, -13566, -13278, -13278, 199 + -12977, -12977, -12665, -12665, -12340, -12340, -12003, -12003, -11656, -11656, 200 + -11297, -11297, -10928, -10928, -10548, -10548, -10159, -10159, -9759, -9759, 201 + -9351, -9351, -8934, -8934, -8509, -8509, -8075, -8075, -7634, -7634, 202 + -7186, -7186, -6731, -6731, -6269, -6269, -5802, -5802, -5329, -5329, 203 + -4852, -4852, -4369, -4369, -3883, -3883, -3393, -3393, -2900, -2900, 204 + -2404, -2404, -1905, -1905, -1405, -1405, -904, -904, -402, -402, 205 + 100, 100, 603, 603, 1105, 1105, 1605, 1605, 2105, 2105, 206 + 2602, 2602, 3097, 3097, 3589, 3589, 4078, 4078, 4563, 4563, 207 + 5043, 5043, 5519, 5519, 5990, 5990, 6455, 6455, 6914, 6914, 208 + 7366, 7366, 7811, 7811, 8249, 8249, 8680, 8680, 9102, 9102, 209 + 9516, 9516, 9920, 9920, 10315, 10315, 10701, 10701, 11077, 11077, 210 + 11442, 11442, 11796, 11796, 12139, 12139, 12471, 12471, 12791, 12791, 211 + 13099, 13099, 13395, 13395, 13678, 13678, 13948, 13948, 14205, 14205, 212 + 14449, 14449, 14679, 14679, 14895, 14895, 15098, 15098, 15286, 15286, 213 + 15459, 15459, 15618, 15618, 15763, 15763, 15892, 15892, 16007, 16007, 214 + 16107, 16107, 16191, 16191, 16260, 16260, 16314, 16314, 16353, 16353, 215 + 16376, 16376, 16384, 16384, 16376, 16376, 16353, 16353, 16314, 16314, 216 + 16260, 16260, 16191, 16191, 16107, 16107, 16007, 16007, 15892, 15892, 217 + 15763, 15763, 15618, 15618, 15459, 15459, 15286, 15286, 15098, 15098, 218 + 14895, 14895, 14679, 14679, 14449, 14449, 14205, 14205, 13948, 13948, 219 + 13678, 13678, 13395, 13395, 13099, 13099, 12791, 12791, 12471, 12471, 220 + 12139, 12139, 11796, 11796, 11442, 11442, 11077, 11077, 10701, 10701, 221 + 10315, 10315, 9920, 9920, 9516, 9516, 9102, 9102, 8680, 8680, 222 + 8249, 8249, 7811, 7811, 7366, 7366, 6914, 6914, 6455, 6455, 223 + 5990, 5990, 5519, 5519, 5043, 5043, 4563, 4563, 4078, 4078, 224 + 3589, 3589, 3097, 3097, 2602, 2602, 2105, 2105, 1605, 1605, 225 + 1105, 1105, 603, 603, 100, 100, -402, -402, -904, -904, 226 + -1405, -1405, -1905, -1905, -2404, -2404, -2900, -2900, -3393, -3393, 227 + -3883, -3883, -4369, -4369, -4852, -4852, -5329, -5329, -5802, -5802, 228 + -6269, -6269, -6731, -6731, -7186, -7186, -7634, -7634, -8075, -8075, 229 + -8509, -8509, -8934, -8934, -9351, -9351, -9759, -9759, -10159, -10159, 230 + -10548, -10548, -10928, -10928, -11297, -11297, -11656, -11656, -12003, -12003, 231 + -12340, -12340, -12665, -12665, -12977, -12977, -13278, -13278, -13566, -13566, 232 + -13842, -13842, -14104, -14104, -14353, -14353, -14589, -14589, -14810, -14810, 233 + -15018, -15018, -15212, -15212, -15392, -15392, -15557, -15557, -15707, -15707, 234 + -15842, -15842, -15963, -15963, -16069, -16069, -16159, -16159, -16234, -16234, 235 + -16294, -16294, -16339, -16339, -16368, -16368, -16382, -16382, -16381, -16381, 236 + -16364, -16364, -16331, -16331, -16284, -16284, -16221, -16221, -16142, -16142, 237 + -16049, -16049, -15940, -15940, -15817, -15817, -15678, -15678, -15525, -15525, 238 + -15357, -15357, -15175, -15175, -14978, -14978, -14767, -14767, -14543, -14543, 239 + -14304, -14304, -14053, -14053, -13788, -13788, -13510, -13510, -13219, -13219, 240 + -12916, -12916, -12600, -12600, -12273, -12273, -11935, -11935, -11585, -11585, 241 + -11224, -11224, -10853, -10853, -10471, -10471, -10079, -10079, -9679, -9679, 242 + -9268, -9268, -8850, -8850, -8423, -8423, -7988, -7988, -7545, -7545, 243 + -7095, -7095, -6639, -6639, -6176, -6176, -5708, -5708, -5234, -5234, 244 + -4756, -4756, -4272, -4272, -3785, -3785, -3294, -3294, -2801, -2801, 245 + -2304, -2304, -1805, -1805, -1305, -1305, -803, -803, -301, -301, 246 + 201, 201, 703, 703, 1205, 1205, 1705, 1705, 2204, 2204, 247 + 2701, 2701, 3196, 3196, 3687, 3687, 4175, 4175, 4659, 4659, 248 + 5139, 5139, 5614, 5614, 6083, 6083, 6547, 6547, 7005, 7005, 249 + 7456, 7456, 7900, 7900, 8336, 8336, 8765, 8765, 9185, 9185, 250 + 9597, 9597, 10000, 10000, 10393, 10393, 10777, 10777, 11150, 11150, 251 + 11513, 11513, 11866, 11866, 12207, 12207, 12536, 12536, 12854, 12854, 252 + 13159, 13159, 13452, 13452, 13733, 13733, 14001, 14001, 14255, 14255, 253 + 14496, 14496, 14723, 14723, 14937, 14937, 15136, 15136, 15322, 15322, 254 + 15492, 15492, 15649, 15649, 15790, 15790, 15917, 15917, 16028, 16028, 255 + 16125, 16125, 16206, 16206, 16272, 16272, 16323, 16323, 16359, 16359, 256 + 16379, 16379, 16383, 16383, 16372, 16372, 16346, 16346, 16305, 16305, 257 + 16248, 16248, 16175, 16175, 16088, 16088, 15985, 15985, 15868, 15868, 258 + 15735, 15735, 15588, 15588, 15426, 15426, 15249, 15249, 15058, 15058, 259 + 14853, 14853, 14634, 14634, 14401, 14401, 14155, 14155, 13895, 13895, 260 + 13622, 13622, 13337, 13337, 13038, 13038, 12728, 12728, 12406, 12406, 261 + 12072, 12072, 11726, 11726, 11370, 11370, 11002, 11002, 10625, 10625, 262 + 10237, 10237, 9840, 9840, 9434, 9434, 9018, 9018, 8594, 8594, 263 + 8162, 8162, 7723, 7723, 7276, 7276, 6822, 6822, 6362, 6362, 264 + 5896, 5896, 5424, 5424, 4948, 4948, 4466, 4466, 3980, 3980, 265 + 3491, 3491, 2998, 2998, 2503, 2503, 2005, 2005, 1505, 1505, 266 + 1004, 1004, 502, 502, 0, 0, -502, -502, -1004, -1004, 267 + -1505, -1505, -2005, -2005, -2503, -2503, -2998, -2998, -3491, -3491, 268 + -3980, -3980, -4466, -4466, -4948, -4948, -5424, -5424, -5896, -5896, 269 + -6362, -6362, -6822, -6822, -7276, -7276, -7723, -7723, -8162, -8162, 270 + -8594, -8594, -9018, -9018, -9434, -9434, -9840, -9840, -10237, -10237, 271 + -10625, -10625, -11002, -11002, -11370, -11370, -11726, -11726, -12072, -12072, 272 + -12406, -12406, -12728, -12728, -13038, -13038, -13337, -13337, -13622, -13622, 273 + -13895, -13895, -14155, -14155, -14401, -14401, -14634, -14634, -14853, -14853, 274 + -15058, -15058, -15249, -15249, -15426, -15426, -15588, -15588, -15735, -15735, 275 + -15868, -15868, -15985, -15985, -16088, -16088, -16175, -16175, -16248, -16248, 276 + -16305, -16305, -16346, -16346, -16372, -16372, -16383, -16383, -16379, -16379, 277 + -16359, -16359, -16323, -16323, -16272, -16272, -16206, -16206, -16125, -16125, 278 + -16028, -16028, -15917, -15917, -15790, -15790, -15649, -15649, -15492, -15492, 279 + -15322, -15322, -15136, -15136, -14937, -14937, -14723, -14723, -14496, -14496, 280 + -14255, -14255, -14001, -14001, -13733, -13733, -13452, -13452, -13159, -13159, 281 + -12854, -12854, -12536, -12536, -12207, -12207, -11866, -11866, -11513, -11513, 282 + -11150, -11150, -10777, -10777, -10393, -10393, -10000, -10000, -9597, -9597, 283 + -9185, -9185, -8765, -8765, -8336, -8336, -7900, -7900, -7456, -7456, 284 + -7005, -7005, -6547, -6547, -6083, -6083, -5614, -5614, -5139, -5139, 285 + -4659, -4659, -4175, -4175, -3687, -3687, -3196, -3196, -2701, -2701, 286 + -2204, -2204, -1705, -1705, -1205, -1205, -703, -703, -201, -201, 287 + 301, 301, 803, 803, 1305, 1305, 1805, 1805, 2304, 2304, 288 + 2801, 2801, 3294, 3294, 3785, 3785, 4272, 4272, 4756, 4756, 289 + 5234, 5234, 5708, 5708, 6176, 6176, 6639, 6639, 7095, 7095, 290 + 7545, 7545, 7988, 7988, 8423, 8423, 8850, 8850, 9268, 9268, 291 + 9679, 9679, 10079, 10079, 10471, 10471, 10853, 10853, 11224, 11224, 292 + 11585, 11585, 11935, 11935, 12273, 12273, 12600, 12600, 12916, 12916, 293 + 13219, 13219, 13510, 13510, 13788, 13788, 14053, 14053, 14304, 14304, 294 + 14543, 14543, 14767, 14767, 14978, 14978, 15175, 15175, 15357, 15357, 295 + 15525, 15525, 15678, 15678, 15817, 15817, 15940, 15940, 16049, 16049, 296 + 16142, 16142, 16221, 16221, 16284, 16284, 16331, 16331, 16364, 16364, 297 + 16381, 16381, 16382, 16382, 16368, 16368, 16339, 16339, 16294, 16294, 298 + 16234, 16234, 16159, 16159, 16069, 16069, 15963, 15963, 15842, 15842, 299 + 15707, 15707, 15557, 15557, 15392, 15392, 15212, 15212, 15018, 15018, 300 + 14810, 14810, 14589, 14589, 14353, 14353, 14104, 14104, 13842, 13842, 301 + 13566, 13566, 13278, 13278, 12977, 12977, 12665, 12665, 12340, 12340, 302 + 12003, 12003, 11656, 11656, 11297, 11297, 10928, 10928, 10548, 10548, 303 + 10159, 10159, 9759, 9759, 9351, 9351, 8934, 8934, 8509, 8509, 304 + 8075, 8075, 7634, 7634, 7186, 7186, 6731, 6731, 6269, 6269, 305 + 5802, 5802, 5329, 5329, 4852, 4852, 4369, 4369, 3883, 3883, 306 + 3393, 3393, 2900, 2900, 2404, 2404, 1905, 1905, 1405, 1405, 307 + 904, 904, 402, 402, -100, -100, -603, -603, -1105, -1105, 308 + -1605, -1605, -2105, -2105, -2602, -2602, -3097, -3097, -3589, -3589, 309 + -4078, -4078, -4563, -4563, -5043, -5043, -5519, -5519, -5990, -5990, 310 + -6455, -6455, -6914, -6914, -7366, -7366, -7811, -7811, -8249, -8249, 311 + -8680, -8680, -9102, -9102, -9516, -9516, -9920, -9920, -10315, -10315, 312 + -10701, -10701, -11077, -11077, -11442, -11442, -11796, -11796, -12139, -12139, 313 + -12471, -12471, -12791, -12791, -13099, -13099, -13395, -13395, -13678, -13678, 314 + -13948, -13948, -14205, -14205, -14449, -14449, -14679, -14679, -14895, -14895, 315 + -15098, -15098, -15286, -15286, -15459, -15459, -15618, -15618, -15763, -15763, 316 + -15892, -15892, -16007, -16007, -16107, -16107, -16191, -16191, -16260, -16260, 317 + -16314, -16314, -16353, -16353, -16376, -16376, -16383, -16383, -16376, -16376, 318 + -16353, -16353, -16314, -16314, -16260, -16260, -16191, -16191, -16107, -16107, 319 + -16007, -16007, -15892, -15892, -15763, -15763, -15618, -15618, -15459, -15459, 320 + -15286, -15286, -15098, -15098, -14895, -14895, -14679, -14679, -14449, -14449, 321 + -14205, -14205, -13948, -13948, -13678, -13678, -13395, -13395, -13099, -13099, 322 + -12791, -12791, -12471, -12471, -12139, -12139, -11796, -11796, -11442, -11442, 323 + -11077, -11077, -10701, -10701, -10315, -10315, -9920, -9920, -9516, -9516, 324 + -9102, -9102, -8680, -8680, -8249, -8249, -7811, -7811, -7366, -7366, 325 + -6914, -6914, -6455, -6455, -5990, -5990, -5519, -5519, -5043, -5043, 326 + -4563, -4563, -4078, -4078, -3589, -3589, -3097, -3097, -2602, -2602, 327 + -2105, -2105, -1605, -1605, -1105, -1105, -603, -603, -100, -100, 328 + 402, 402, 904, 904, 1405, 1405, 1905, 1905, 2404, 2404, 329 + 2900, 2900, 3393, 3393, 3883, 3883, 4369, 4369, 4852, 4852, 330 + 5329, 5329, 5802, 5802, 6269, 6269, 6731, 6731, 7186, 7186, 331 + 7634, 7634, 8075, 8075, 8509, 8509, 8934, 8934, 9351, 9351, 332 + 9759, 9759, 10159, 10159, 10548, 10548, 10928, 10928, 11297, 11297, 333 + 11656, 11656, 12003, 12003, 12340, 12340, 12665, 12665, 12977, 12977, 334 + 13278, 13278, 13566, 13566, 13842, 13842, 14104, 14104, 14353, 14353, 335 + 14589, 14589, 14810, 14810, 15018, 15018, 15212, 15212, 15392, 15392, 336 + 15557, 15557, 15707, 15707, 15842, 15842, 15963, 15963, 16069, 16069, 337 + 16159, 16159, 16234, 16234, 16294, 16294, 16339, 16339, 16368, 16368, 338 + 16382, 16382, 16381, 16381, 16364, 16364, 16331, 16331, 16284, 16284, 339 + 16221, 16221, 16142, 16142, 16049, 16049, 15940, 15940, 15817, 15817, 340 + 15678, 15678, 15525, 15525, 15357, 15357, 15175, 15175, 14978, 14978, 341 + 14767, 14767, 14543, 14543, 14304, 14304, 14053, 14053, 13788, 13788, 342 + 13510, 13510, 13219, 13219, 12916, 12916, 12600, 12600, 12273, 12273, 343 + 11935, 11935, 11585, 11585, 11224, 11224, 10853, 10853, 10471, 10471, 344 + 10079, 10079, 9679, 9679, 9268, 9268, 8850, 8850, 8423, 8423, 345 + 7988, 7988, 7545, 7545, 7095, 7095, 6639, 6639, 6176, 6176, 346 + 5708, 5708, 5234, 5234, 4756, 4756, 4272, 4272, 3785, 3785, 347 + 3294, 3294, 2801, 2801, 2304, 2304, 1805, 1805, 1305, 1305, 348 + 803, 803, 301, 301, -201, -201, -703, -703, -1205, -1205, 349 + -1705, -1705, -2204, -2204, -2701, -2701, -3196, -3196, -3687, -3687, 350 + -4175, -4175, -4659, -4659, -5139, -5139, -5614, -5614, -6083, -6083, 351 + -6547, -6547, -7005, -7005, -7456, -7456, -7900, -7900, -8336, -8336, 352 + -8765, -8765, -9185, -9185, -9597, -9597, -10000, -10000, -10393, -10393, 353 + -10777, -10777, -11150, -11150, -11513, -11513, -11866, -11866, -12207, -12207, 354 + -12536, -12536, -12854, -12854, -13159, -13159, -13452, -13452, -13733, -13733, 355 + -14001, -14001, -14255, -14255, -14496, -14496, -14723, -14723, -14937, -14937, 356 + -15136, -15136, -15322, -15322, -15492, -15492, -15649, -15649, -15790, -15790, 357 + -15917, -15917, -16028, -16028, -16125, -16125, -16206, -16206, -16272, -16272, 358 + -16323, -16323, -16359, -16359, -16379, -16379, -16383, -16383, -16372, -16372, 359 + -16346, -16346, -16305, -16305, -16248, -16248, -16175, -16175, -16088, -16088, 360 + -15985, -15985, -15868, -15868, -15735, -15735, -15588, -15588, -15426, -15426, 361 + -15249, -15249, -15058, -15058, -14853, -14853, -14634, -14634, -14401, -14401, 362 + -14155, -14155, -13895, -13895, -13622, -13622, -13337, -13337, -13038, -13038, 363 + -12728, -12728, -12406, -12406, -12072, -12072, -11726, -11726, -11370, -11370, 364 + -11002, -11002, -10625, -10625, -10237, -10237, -9840, -9840, -9434, -9434, 365 + -9018, -9018, -8594, -8594, -8162, -8162, -7723, -7723, -7276, -7276, 366 + -6822, -6822, -6362, -6362, -5896, -5896, -5424, -5424, -4948, -4948, 367 + -4466, -4466, -3980, -3980, -3491, -3491, -2998, -2998, -2503, -2503, 368 + -2005, -2005, -1505, -1505, -1004, -1004, -502, -502 369 + }; 370 + /*****************************************************************************/ 371 + void 372 + easysnd_testtone(struct easycap *peasycap, int audio_fill) 373 + { 374 + int i1; 375 + unsigned char *p2; 376 + struct data_buffer *paudio_buffer; 377 + 378 + JOT(8, "%i=audio_fill\n", audio_fill); 379 + 380 + paudio_buffer = &peasycap->audio_buffer[audio_fill]; 381 + 382 + p2 = (unsigned char *)(paudio_buffer->pgo); 383 + for (i1 = 0; i1 < PAGE_SIZE; i1 += 4, p2 += 4) { 384 + *p2 = (unsigned char) (0x00FF & tones[i1/2]); 385 + *(p2 + 1) = (unsigned char)((0xFF00 & tones[i1/2]) >> 8); 386 + *(p2 + 2) = (unsigned char) (0x00FF & tones[i1/2 + 1]); 387 + *(p2 + 3) = (unsigned char)((0xFF00 & tones[i1/2 + 1]) >> 8); 388 + } 389 + return; 390 + } 391 + #endif /*EASYCAP_TESTTONE*/ 392 + /*****************************************************************************/