blob: 447953a4e80c59f502a7c12428505fc4f6b13465 [file] [log] [blame]
R.M. Thomas702422b2010-06-18 12:29:49 -07001/******************************************************************************
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
Frederic Weisbecker5ef06832010-08-09 03:28:40 +020028#include <linux/smp_lock.h>
R.M. Thomas702422b2010-06-18 12:29:49 -070029#include "easycap.h"
30#include "easycap_debug.h"
31#include "easycap_standard.h"
32#include "easycap_ioctl.h"
33
34/*--------------------------------------------------------------------------*/
35/*
36 * UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
37 * FOLLOWING:
38 * peasycap->standard_offset
Mike Thomasf36bc372010-11-07 20:00:35 +000039 * peasycap->inputset[peasycap->input].standard_offset
R.M. Thomas702422b2010-06-18 12:29:49 -070040 * peasycap->fps
41 * peasycap->usec
42 * peasycap->tolerate
Mike Thomas40b8d502010-11-07 20:02:15 +000043 * peasycap->skip
R.M. Thomas702422b2010-06-18 12:29:49 -070044 */
45/*---------------------------------------------------------------------------*/
46int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
47{
Mike Thomas3d423e92010-07-11 10:51:13 +010048struct easycap_standard const *peasycap_standard;
R.M. Thomas702422b2010-06-18 12:29:49 -070049__u16 reg, set;
Mike Thomasf36bc372010-11-07 20:00:35 +000050int ir, rc, need, k;
R.M. Thomas702422b2010-06-18 12:29:49 -070051unsigned int itwas, isnow;
Mike Thomasf36bc372010-11-07 20:00:35 +000052bool resubmit;
R.M. Thomas702422b2010-06-18 12:29:49 -070053
Mike Thomase68703c2010-11-07 19:58:55 +000054if (NULL == peasycap) {
55 SAY("ERROR: peasycap is NULL\n");
56 return -EFAULT;
57}
R.M. Thomas702422b2010-06-18 12:29:49 -070058if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +000059 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -070060 return -EFAULT;
61}
62peasycap_standard = &easycap_standard[0];
63while (0xFFFF != peasycap_standard->mask) {
Mike Thomas40b8d502010-11-07 20:02:15 +000064 if (std_id == peasycap_standard->v4l2_standard.id)
R.M. Thomas702422b2010-06-18 12:29:49 -070065 break;
66 peasycap_standard++;
67}
68if (0xFFFF == peasycap_standard->mask) {
Mike Thomas40b8d502010-11-07 20:02:15 +000069 peasycap_standard = &easycap_standard[0];
70 while (0xFFFF != peasycap_standard->mask) {
71 if (std_id & peasycap_standard->v4l2_standard.id)
72 break;
73 peasycap_standard++;
74 }
75}
76if (0xFFFF == peasycap_standard->mask) {
Mike Thomase68703c2010-11-07 19:58:55 +000077 SAM("ERROR: 0x%08X=std_id: standard not found\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -070078 (unsigned int)std_id);
79 return -EINVAL;
80}
Mike Thomasf36bc372010-11-07 20:00:35 +000081SAM("selected standard: %s\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -070082 &(peasycap_standard->v4l2_standard.name[0]));
83if (peasycap->standard_offset == \
84 (int)(peasycap_standard - &easycap_standard[0])) {
Mike Thomase68703c2010-11-07 19:58:55 +000085 SAM("requested standard already in effect\n");
R.M. Thomas702422b2010-06-18 12:29:49 -070086 return 0;
87}
88peasycap->standard_offset = (int)(peasycap_standard - &easycap_standard[0]);
Mike Thomasf36bc372010-11-07 20:00:35 +000089for (k = 0; k < INPUT_MANY; k++) {
90 if (!peasycap->inputset[k].standard_offset_ok) {
91 peasycap->inputset[k].standard_offset = \
92 peasycap->standard_offset;
93 }
94}
95if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
96 peasycap->inputset[peasycap->input].standard_offset = \
97 peasycap->standard_offset;
98 peasycap->inputset[peasycap->input].standard_offset_ok = 1;
99} else
100 JOM(8, "%i=peasycap->input\n", peasycap->input);
R.M. Thomas702422b2010-06-18 12:29:49 -0700101peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator / \
102 peasycap_standard->v4l2_standard.frameperiod.numerator;
Mike Thomasf36bc372010-11-07 20:00:35 +0000103switch (peasycap->fps) {
Mike Thomas40b8d502010-11-07 20:02:15 +0000104case 6:
Mike Thomasf36bc372010-11-07 20:00:35 +0000105case 30: {
106 peasycap->ntsc = true;
107 break;
108}
Mike Thomas40b8d502010-11-07 20:02:15 +0000109case 5:
Mike Thomasf36bc372010-11-07 20:00:35 +0000110case 25: {
111 peasycap->ntsc = false;
112 break;
113}
114default: {
115 SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
116 return -ENOENT;
117}
R.M. Thomas702422b2010-06-18 12:29:49 -0700118}
Mike Thomase68703c2010-11-07 19:58:55 +0000119JOM(8, "%i frames-per-second\n", peasycap->fps);
Mike Thomas40b8d502010-11-07 20:02:15 +0000120if (0x8000 & peasycap_standard->mask) {
121 peasycap->skip = 5;
122 peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
123 peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
124} else {
125 peasycap->skip = 0;
126 peasycap->usec = 1000000 / (2 * peasycap->fps);
127 peasycap->tolerate = 1000 * (25 / peasycap->fps);
128}
Mike Thomasf36bc372010-11-07 20:00:35 +0000129if (peasycap->video_isoc_streaming) {
130 resubmit = true;
131 kill_video_urbs(peasycap);
132} else
133 resubmit = false;
R.M. Thomas702422b2010-06-18 12:29:49 -0700134/*--------------------------------------------------------------------------*/
135/*
136 * SAA7113H DATASHEET PAGE 44, TABLE 42
137 */
138/*--------------------------------------------------------------------------*/
139need = 0; itwas = 0; reg = 0x00; set = 0x00;
140switch (peasycap_standard->mask & 0x000F) {
141case NTSC_M_JP: {
142 reg = 0x0A; set = 0x95;
143 ir = read_saa(peasycap->pusb_device, reg);
144 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000145 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
R.M. Thomas702422b2010-06-18 12:29:49 -0700146 else
147 itwas = (unsigned int)ir;
R.M. Thomas702422b2010-06-18 12:29:49 -0700148 rc = write_saa(peasycap->pusb_device, reg, set);
149 if (0 != rc)
Mike Thomase68703c2010-11-07 19:58:55 +0000150 SAM("ERROR: failed to set SAA register " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700151 "0x%02X to 0x%02X for JP standard\n", reg, set);
152 else {
153 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
154 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000155 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700156 "to 0x%02X\n", reg, isnow);
157 else
Mike Thomase68703c2010-11-07 19:58:55 +0000158 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700159 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
R.M. Thomas702422b2010-06-18 12:29:49 -0700160 }
161
162 reg = 0x0B; set = 0x48;
163 ir = read_saa(peasycap->pusb_device, reg);
164 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000165 SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
R.M. Thomas702422b2010-06-18 12:29:49 -0700166 else
167 itwas = (unsigned int)ir;
R.M. Thomas702422b2010-06-18 12:29:49 -0700168 rc = write_saa(peasycap->pusb_device, reg, set);
169 if (0 != rc)
Mike Thomase68703c2010-11-07 19:58:55 +0000170 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700171 "for JP standard\n", reg, set);
172 else {
173 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
174 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000175 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700176 "to 0x%02X\n", reg, isnow);
177 else
Mike Thomase68703c2010-11-07 19:58:55 +0000178 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700179 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
R.M. Thomas702422b2010-06-18 12:29:49 -0700180 }
181/*--------------------------------------------------------------------------*/
182/*
183 * NOTE: NO break HERE: RUN ON TO NEXT CASE
184 */
185/*--------------------------------------------------------------------------*/
186}
187case NTSC_M:
188case PAL_BGHIN: {
189 reg = 0x0E; set = 0x01; need = 1; break;
190}
191case NTSC_N_443:
192case PAL_60: {
193 reg = 0x0E; set = 0x11; need = 1; break;
194}
195case NTSC_443:
196case PAL_Nc: {
197 reg = 0x0E; set = 0x21; need = 1; break;
198}
199case NTSC_N:
200case PAL_M: {
201 reg = 0x0E; set = 0x31; need = 1; break;
202}
203case SECAM: {
204 reg = 0x0E; set = 0x51; need = 1; break;
205}
206default:
207 break;
208}
209/*--------------------------------------------------------------------------*/
210if (need) {
211 ir = read_saa(peasycap->pusb_device, reg);
212 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000213 SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
R.M. Thomas702422b2010-06-18 12:29:49 -0700214 else
215 itwas = (unsigned int)ir;
R.M. Thomas702422b2010-06-18 12:29:49 -0700216 rc = write_saa(peasycap->pusb_device, reg, set);
217 if (0 != write_saa(peasycap->pusb_device, reg, set)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000218 SAM("ERROR: failed to set SAA register " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700219 "0x%02X to 0x%02X for table 42\n", reg, set);
220 } else {
221 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
222 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000223 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700224 "to 0x%02X\n", reg, isnow);
225 else
Mike Thomase68703c2010-11-07 19:58:55 +0000226 JOM(8, "SAA register 0x%02X changed " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700227 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
228 }
229}
230/*--------------------------------------------------------------------------*/
231/*
232 * SAA7113H DATASHEET PAGE 41
233 */
234/*--------------------------------------------------------------------------*/
235reg = 0x08;
236ir = read_saa(peasycap->pusb_device, reg);
237if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000238 SAM("ERROR: failed to read SAA register 0x%02X " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700239 "so cannot reset\n", reg);
240else {
241 itwas = (unsigned int)ir;
242 if (peasycap_standard->mask & 0x0001)
243 set = itwas | 0x40 ;
244 else
245 set = itwas & ~0x40 ;
Mike Thomasf36bc372010-11-07 20:00:35 +0000246 rc = write_saa(peasycap->pusb_device, reg, set);
247 if (0 != rc)
248 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
249 reg, set);
250 else {
251 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
252 if (0 > ir)
253 JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
254 reg, isnow);
255 else
256 JOM(8, "SAA register 0x%02X changed " \
257 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
R.M. Thomas702422b2010-06-18 12:29:49 -0700258 }
259}
260/*--------------------------------------------------------------------------*/
261/*
262 * SAA7113H DATASHEET PAGE 51, TABLE 57
263 */
264/*---------------------------------------------------------------------------*/
265reg = 0x40;
266ir = read_saa(peasycap->pusb_device, reg);
267if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000268 SAM("ERROR: failed to read SAA register 0x%02X " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700269 "so cannot reset\n", reg);
270else {
271 itwas = (unsigned int)ir;
272 if (peasycap_standard->mask & 0x0001)
273 set = itwas | 0x80 ;
274 else
275 set = itwas & ~0x80 ;
Mike Thomasf36bc372010-11-07 20:00:35 +0000276 rc = write_saa(peasycap->pusb_device, reg, set);
277 if (0 != rc)
278 SAM("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 JOM(8, "SAA register 0x%02X changed to 0x%02X\n", \
284 reg, isnow);
285 else
286 JOM(8, "SAA register 0x%02X changed " \
287 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
R.M. Thomas702422b2010-06-18 12:29:49 -0700288 }
289}
290/*--------------------------------------------------------------------------*/
291/*
292 * SAA7113H DATASHEET PAGE 53, TABLE 66
293 */
294/*--------------------------------------------------------------------------*/
295reg = 0x5A;
296ir = read_saa(peasycap->pusb_device, reg);
297if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000298 SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
R.M. Thomas702422b2010-06-18 12:29:49 -0700299 itwas = (unsigned int)ir;
300 if (peasycap_standard->mask & 0x0001)
301 set = 0x0A ;
302 else
303 set = 0x07 ;
R.M. Thomas702422b2010-06-18 12:29:49 -0700304 if (0 != write_saa(peasycap->pusb_device, reg, set))
Mike Thomase68703c2010-11-07 19:58:55 +0000305 SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700306 reg, set);
307 else {
308 isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
309 if (0 > ir)
Mike Thomase68703c2010-11-07 19:58:55 +0000310 JOM(8, "SAA register 0x%02X changed "
R.M. Thomas702422b2010-06-18 12:29:49 -0700311 "to 0x%02X\n", reg, isnow);
312 else
Mike Thomase68703c2010-11-07 19:58:55 +0000313 JOM(8, "SAA register 0x%02X changed "
R.M. Thomas702422b2010-06-18 12:29:49 -0700314 "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
315 }
Mike Thomasf36bc372010-11-07 20:00:35 +0000316if (true == resubmit)
317 submit_video_urbs(peasycap);
R.M. Thomas702422b2010-06-18 12:29:49 -0700318return 0;
319}
320/*****************************************************************************/
321/*--------------------------------------------------------------------------*/
322/*
Mike Thomasf36bc372010-11-07 20:00:35 +0000323 * THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
324 * A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
325 *
R.M. Thomas702422b2010-06-18 12:29:49 -0700326 * PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
327 * THIS ROUTINE UPDATES THE FOLLOWING:
328 * peasycap->format_offset
Mike Thomasf36bc372010-11-07 20:00:35 +0000329 * peasycap->inputset[peasycap->input].format_offset
R.M. Thomas702422b2010-06-18 12:29:49 -0700330 * peasycap->pixelformat
R.M. Thomas702422b2010-06-18 12:29:49 -0700331 * peasycap->height
332 * peasycap->width
333 * peasycap->bytesperpixel
334 * peasycap->byteswaporder
335 * peasycap->decimatepixel
336 * peasycap->frame_buffer_used
337 * peasycap->videofieldamount
338 * peasycap->offerfields
339 *
340 * IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
341 * IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
342 * ERRORS RETURN A NEGATIVE NUMBER.
343 */
344/*--------------------------------------------------------------------------*/
345int adjust_format(struct easycap *peasycap, \
346 __u32 width, __u32 height, __u32 pixelformat, int field, bool try)
347{
348struct easycap_format *peasycap_format, *peasycap_best_format;
349__u16 mask;
350struct usb_device *p;
Mike Thomasf36bc372010-11-07 20:00:35 +0000351int miss, multiplier, best, k;
Mike Thomas40b8d502010-11-07 20:02:15 +0000352char bf[5], fo[32], *pc;
R.M. Thomas702422b2010-06-18 12:29:49 -0700353__u32 uc;
Mike Thomasf36bc372010-11-07 20:00:35 +0000354bool resubmit;
R.M. Thomas702422b2010-06-18 12:29:49 -0700355
Mike Thomase68703c2010-11-07 19:58:55 +0000356if (NULL == peasycap) {
R.M. Thomas702422b2010-06-18 12:29:49 -0700357 SAY("ERROR: peasycap is NULL\n");
358 return -EFAULT;
359}
Mike Thomasf36bc372010-11-07 20:00:35 +0000360if (0 > peasycap->standard_offset) {
361 JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
362 return -EBUSY;
363}
R.M. Thomas702422b2010-06-18 12:29:49 -0700364p = peasycap->pusb_device;
365if ((struct usb_device *)NULL == p) {
Mike Thomase68703c2010-11-07 19:58:55 +0000366 SAM("ERROR: peaycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700367 return -EFAULT;
368}
369pc = &bf[0];
Mike Thomas40b8d502010-11-07 20:02:15 +0000370uc = pixelformat;
371memcpy((void *)pc, (void *)(&uc), 4);
372bf[4] = 0;
373mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
Mike Thomase68703c2010-11-07 19:58:55 +0000374SAM("sought: %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700375 width, height, pc, pixelformat, field, mask);
Mike Thomas40b8d502010-11-07 20:02:15 +0000376switch (field) {
377case V4L2_FIELD_ANY: {
378 strcpy(&fo[0], "V4L2_FIELD_ANY ");
379 break;
380}
381case V4L2_FIELD_NONE: {
382 strcpy(&fo[0], "V4L2_FIELD_NONE");
383 break;
384}
385case V4L2_FIELD_TOP: {
386 strcpy(&fo[0], "V4L2_FIELD_TOP");
387 break;
388}
389case V4L2_FIELD_BOTTOM: {
390 strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
391 break;
392}
393case V4L2_FIELD_INTERLACED: {
394 strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
395 break;
396}
397case V4L2_FIELD_SEQ_TB: {
398 strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
399 break;
400}
401case V4L2_FIELD_SEQ_BT: {
402 strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
403 break;
404}
405case V4L2_FIELD_ALTERNATE: {
406 strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
407 break;
408}
409case V4L2_FIELD_INTERLACED_TB: {
410 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
411 break;
412}
413case V4L2_FIELD_INTERLACED_BT: {
414 strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
415 break;
416}
417default: {
418 strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN ");
419 break;
420}
421}
422SAM("sought: %s\n", &fo[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -0700423if (V4L2_FIELD_ANY == field) {
Mike Thomas40b8d502010-11-07 20:02:15 +0000424 field = V4L2_FIELD_NONE;
425 SAM("prefer: V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700426}
427peasycap_best_format = (struct easycap_format *)NULL;
428peasycap_format = &easycap_format[0];
429while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
Mike Thomase68703c2010-11-07 19:58:55 +0000430 JOM(16, ".> %i %i 0x%08X %ix%i\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700431 peasycap_format->mask & 0x01,
432 peasycap_format->v4l2_format.fmt.pix.field,
433 peasycap_format->v4l2_format.fmt.pix.pixelformat,
434 peasycap_format->v4l2_format.fmt.pix.width,
435 peasycap_format->v4l2_format.fmt.pix.height);
436
Mike Thomas40b8d502010-11-07 20:02:15 +0000437 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
R.M. Thomas702422b2010-06-18 12:29:49 -0700438 (peasycap_format->v4l2_format.fmt.pix.field == field) && \
439 (peasycap_format->v4l2_format.fmt.pix.pixelformat == \
440 pixelformat) && \
441 (peasycap_format->v4l2_format.fmt.pix.width == width) && \
442 (peasycap_format->v4l2_format.fmt.pix.height == height)) {
443 peasycap_best_format = peasycap_format;
444 break;
445 }
446 peasycap_format++;
447}
448if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
Mike Thomase68703c2010-11-07 19:58:55 +0000449 SAM("cannot do: %ix%i with standard mask 0x%02X\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700450 width, height, mask);
451 peasycap_format = &easycap_format[0]; best = -1;
452 while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
Mike Thomas40b8d502010-11-07 20:02:15 +0000453 if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) && \
R.M. Thomas702422b2010-06-18 12:29:49 -0700454 (peasycap_format->v4l2_format.fmt.pix\
455 .field == field) && \
456 (peasycap_format->v4l2_format.fmt.pix\
457 .pixelformat == pixelformat)) {
458 miss = abs(peasycap_format->\
459 v4l2_format.fmt.pix.width - width);
460 if ((best > miss) || (best < 0)) {
461 best = miss;
462 peasycap_best_format = peasycap_format;
463 if (!miss)
464 break;
465 }
466 }
467 peasycap_format++;
468 }
469 if (-1 == best) {
Mike Thomase68703c2010-11-07 19:58:55 +0000470 SAM("cannot do %ix... with standard mask 0x%02X\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700471 width, mask);
Mike Thomase68703c2010-11-07 19:58:55 +0000472 SAM("cannot do ...x%i with standard mask 0x%02X\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700473 height, mask);
Mike Thomase68703c2010-11-07 19:58:55 +0000474 SAM(" %ix%i unmatched\n", width, height);
R.M. Thomas702422b2010-06-18 12:29:49 -0700475 return peasycap->format_offset;
476 }
477}
478if ((struct easycap_format *)NULL == peasycap_best_format) {
Mike Thomase68703c2010-11-07 19:58:55 +0000479 SAM("MISTAKE: peasycap_best_format is NULL");
R.M. Thomas702422b2010-06-18 12:29:49 -0700480 return -EINVAL;
481}
482peasycap_format = peasycap_best_format;
483
484/*...........................................................................*/
485if (true == try)
486 return (int)(peasycap_best_format - &easycap_format[0]);
487/*...........................................................................*/
488
489if (false != try) {
Mike Thomase68703c2010-11-07 19:58:55 +0000490 SAM("MISTAKE: true==try where is should be false\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700491 return -EINVAL;
492}
Mike Thomase68703c2010-11-07 19:58:55 +0000493SAM("actioning: %ix%i %s\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700494 peasycap_format->v4l2_format.fmt.pix.width, \
495 peasycap_format->v4l2_format.fmt.pix.height,
496 &peasycap_format->name[0]);
497peasycap->height = peasycap_format->v4l2_format.fmt.pix.height;
498peasycap->width = peasycap_format->v4l2_format.fmt.pix.width;
499peasycap->pixelformat = peasycap_format->v4l2_format.fmt.pix.pixelformat;
R.M. Thomas702422b2010-06-18 12:29:49 -0700500peasycap->format_offset = (int)(peasycap_format - &easycap_format[0]);
Mike Thomasf36bc372010-11-07 20:00:35 +0000501
502
503for (k = 0; k < INPUT_MANY; k++) {
504 if (!peasycap->inputset[k].format_offset_ok) {
505 peasycap->inputset[k].format_offset = \
506 peasycap->format_offset;
507 }
508}
509if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
510 peasycap->inputset[peasycap->input].format_offset = \
511 peasycap->format_offset;
512 peasycap->inputset[peasycap->input].format_offset_ok = 1;
513} else
514 JOM(8, "%i=peasycap->input\n", peasycap->input);
515
516
517
Mike Thomas40b8d502010-11-07 20:02:15 +0000518peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
R.M. Thomas702422b2010-06-18 12:29:49 -0700519if (0x0100 & peasycap_format->mask)
520 peasycap->byteswaporder = true;
521else
522 peasycap->byteswaporder = false;
Mike Thomas40b8d502010-11-07 20:02:15 +0000523if (0x0200 & peasycap_format->mask)
524 peasycap->skip = 5;
525else
526 peasycap->skip = 0;
R.M. Thomas702422b2010-06-18 12:29:49 -0700527if (0x0800 & peasycap_format->mask)
528 peasycap->decimatepixel = true;
529else
530 peasycap->decimatepixel = false;
531if (0x1000 & peasycap_format->mask)
532 peasycap->offerfields = true;
533else
534 peasycap->offerfields = false;
535if (true == peasycap->decimatepixel)
536 multiplier = 2;
537else
538 multiplier = 1;
539peasycap->videofieldamount = multiplier * peasycap->width * \
540 multiplier * peasycap->height;
541peasycap->frame_buffer_used = peasycap->bytesperpixel * \
542 peasycap->width * peasycap->height;
Mike Thomasf36bc372010-11-07 20:00:35 +0000543if (peasycap->video_isoc_streaming) {
544 resubmit = true;
545 kill_video_urbs(peasycap);
546} else
547 resubmit = false;
R.M. Thomas702422b2010-06-18 12:29:49 -0700548/*---------------------------------------------------------------------------*/
549/*
550 * PAL
551 */
552/*---------------------------------------------------------------------------*/
553if (0 == (0x01 & peasycap_format->mask)) {
554 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
555 (576 == \
556 peasycap_format->v4l2_format.fmt.pix.height)) || \
557 ((360 == \
558 peasycap_format->v4l2_format.fmt.pix.width) && \
559 (288 == \
560 peasycap_format->v4l2_format.fmt.pix.height))) {
561 if (0 != set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000562 SAM("ERROR: set_resolution() failed\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700563 return -EINVAL;
564 }
565 } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) && \
566 (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
567 if (0 != set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000568 SAM("ERROR: set_resolution() failed\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700569 return -EINVAL;
570 }
571 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
572 (480 == \
573 peasycap_format->v4l2_format.fmt.pix.height)) || \
574 ((320 == \
575 peasycap_format->v4l2_format.fmt.pix.width) && \
576 (240 == \
577 peasycap_format->v4l2_format.fmt.pix.height))) {
578 if (0 != set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000579 SAM("ERROR: set_resolution() failed\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700580 return -EINVAL;
581 }
582 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000583 SAM("MISTAKE: bad format, cannot set resolution\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700584 return -EINVAL;
585 }
586/*---------------------------------------------------------------------------*/
587/*
588 * NTSC
589 */
590/*---------------------------------------------------------------------------*/
591} else {
592 if (((720 == peasycap_format->v4l2_format.fmt.pix.width) && \
593 (480 == \
594 peasycap_format->v4l2_format.fmt.pix.height)) || \
595 ((360 == \
596 peasycap_format->v4l2_format.fmt.pix.width) && \
597 (240 == \
598 peasycap_format->v4l2_format.fmt.pix.height))) {
599 if (0 != set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000600 SAM("ERROR: set_resolution() failed\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700601 return -EINVAL;
602 }
603 } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) && \
604 (480 == \
605 peasycap_format->v4l2_format.fmt.pix.height)) || \
606 ((320 == \
607 peasycap_format->v4l2_format.fmt.pix.width) && \
608 (240 == \
609 peasycap_format->v4l2_format.fmt.pix.height))) {
610 if (0 != set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000611 SAM("ERROR: set_resolution() failed\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700612 return -EINVAL;
613 }
614 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000615 SAM("MISTAKE: bad format, cannot set resolution\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700616 return -EINVAL;
617 }
618}
619/*---------------------------------------------------------------------------*/
Mike Thomasf36bc372010-11-07 20:00:35 +0000620if (true == resubmit)
621 submit_video_urbs(peasycap);
R.M. Thomas702422b2010-06-18 12:29:49 -0700622return (int)(peasycap_best_format - &easycap_format[0]);
623}
624/*****************************************************************************/
625int adjust_brightness(struct easycap *peasycap, int value)
626{
627unsigned int mood;
Mike Thomasf36bc372010-11-07 20:00:35 +0000628int i1, k;
R.M. Thomas702422b2010-06-18 12:29:49 -0700629
Mike Thomase68703c2010-11-07 19:58:55 +0000630if (NULL == peasycap) {
631 SAY("ERROR: peasycap is NULL\n");
632 return -EFAULT;
633}
R.M. Thomas702422b2010-06-18 12:29:49 -0700634if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000635 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700636 return -EFAULT;
637}
638i1 = 0;
639while (0xFFFFFFFF != easycap_control[i1].id) {
640 if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
641 if ((easycap_control[i1].minimum > value) || \
642 (easycap_control[i1].maximum < value))
643 value = easycap_control[i1].default_value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000644
645 if ((easycap_control[i1].minimum <= peasycap->brightness) && \
646 (easycap_control[i1].maximum >= \
647 peasycap->brightness)) {
648 if (peasycap->brightness == value) {
649 SAM("unchanged brightness at 0x%02X\n", \
650 value);
651 return 0;
652 }
653 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700654 peasycap->brightness = value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000655 for (k = 0; k < INPUT_MANY; k++) {
656 if (!peasycap->inputset[k].brightness_ok)
657 peasycap->inputset[k].brightness = \
658 peasycap->brightness;
659 }
660 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
661 peasycap->inputset[peasycap->input].brightness = \
662 peasycap->brightness;
663 peasycap->inputset[peasycap->input].brightness_ok = 1;
664 } else
665 JOM(8, "%i=peasycap->input\n", peasycap->input);
R.M. Thomas702422b2010-06-18 12:29:49 -0700666 mood = 0x00FF & (unsigned int)peasycap->brightness;
R.M. Thomas702422b2010-06-18 12:29:49 -0700667 if (!write_saa(peasycap->pusb_device, 0x0A, mood)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000668 SAM("adjusting brightness to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700669 return 0;
670 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000671 SAM("WARNING: failed to adjust brightness " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700672 "to 0x%02X\n", mood);
673 return -ENOENT;
674 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700675 break;
676 }
677 i1++;
678}
Mike Thomase68703c2010-11-07 19:58:55 +0000679SAM("WARNING: failed to adjust brightness: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700680return -ENOENT;
681}
682/*****************************************************************************/
683int adjust_contrast(struct easycap *peasycap, int value)
684{
685unsigned int mood;
Mike Thomasf36bc372010-11-07 20:00:35 +0000686int i1, k;
R.M. Thomas702422b2010-06-18 12:29:49 -0700687
Mike Thomase68703c2010-11-07 19:58:55 +0000688if (NULL == peasycap) {
689 SAY("ERROR: peasycap is NULL\n");
690 return -EFAULT;
691}
R.M. Thomas702422b2010-06-18 12:29:49 -0700692if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000693 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700694 return -EFAULT;
695}
696i1 = 0;
697while (0xFFFFFFFF != easycap_control[i1].id) {
698 if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
699 if ((easycap_control[i1].minimum > value) || \
700 (easycap_control[i1].maximum < value))
701 value = easycap_control[i1].default_value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000702
703
704
705 if ((easycap_control[i1].minimum <= peasycap->contrast) && \
706 (easycap_control[i1].maximum >= \
707 peasycap->contrast)) {
708 if (peasycap->contrast == value) {
709 SAM("unchanged contrast at 0x%02X\n", value);
710 return 0;
711 }
712 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700713 peasycap->contrast = value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000714 for (k = 0; k < INPUT_MANY; k++) {
715 if (!peasycap->inputset[k].contrast_ok) {
716 peasycap->inputset[k].contrast = \
717 peasycap->contrast;
718 }
719 }
720 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
721 peasycap->inputset[peasycap->input].contrast = \
722 peasycap->contrast;
723 peasycap->inputset[peasycap->input].contrast_ok = 1;
724 } else
725 JOM(8, "%i=peasycap->input\n", peasycap->input);
R.M. Thomas702422b2010-06-18 12:29:49 -0700726 mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
R.M. Thomas702422b2010-06-18 12:29:49 -0700727 if (!write_saa(peasycap->pusb_device, 0x0B, mood)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000728 SAM("adjusting contrast to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700729 return 0;
730 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000731 SAM("WARNING: failed to adjust contrast to " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700732 "0x%02X\n", mood);
733 return -ENOENT;
734 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700735 break;
736 }
737 i1++;
738}
Mike Thomase68703c2010-11-07 19:58:55 +0000739SAM("WARNING: failed to adjust contrast: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700740return -ENOENT;
741}
742/*****************************************************************************/
743int adjust_saturation(struct easycap *peasycap, int value)
744{
745unsigned int mood;
Mike Thomasf36bc372010-11-07 20:00:35 +0000746int i1, k;
R.M. Thomas702422b2010-06-18 12:29:49 -0700747
Mike Thomase68703c2010-11-07 19:58:55 +0000748if (NULL == peasycap) {
749 SAY("ERROR: peasycap is NULL\n");
750 return -EFAULT;
751}
R.M. Thomas702422b2010-06-18 12:29:49 -0700752if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000753 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700754 return -EFAULT;
755}
756i1 = 0;
757while (0xFFFFFFFF != easycap_control[i1].id) {
758 if (V4L2_CID_SATURATION == easycap_control[i1].id) {
759 if ((easycap_control[i1].minimum > value) || \
760 (easycap_control[i1].maximum < value))
761 value = easycap_control[i1].default_value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000762
763
764 if ((easycap_control[i1].minimum <= peasycap->saturation) && \
765 (easycap_control[i1].maximum >= \
766 peasycap->saturation)) {
767 if (peasycap->saturation == value) {
768 SAM("unchanged saturation at 0x%02X\n", \
769 value);
770 return 0;
771 }
772 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700773 peasycap->saturation = value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000774 for (k = 0; k < INPUT_MANY; k++) {
775 if (!peasycap->inputset[k].saturation_ok) {
776 peasycap->inputset[k].saturation = \
777 peasycap->saturation;
778 }
779 }
780 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
781 peasycap->inputset[peasycap->input].saturation = \
782 peasycap->saturation;
783 peasycap->inputset[peasycap->input].saturation_ok = 1;
784 } else
785 JOM(8, "%i=peasycap->input\n", peasycap->input);
R.M. Thomas702422b2010-06-18 12:29:49 -0700786 mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
R.M. Thomas702422b2010-06-18 12:29:49 -0700787 if (!write_saa(peasycap->pusb_device, 0x0C, mood)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000788 SAM("adjusting saturation to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700789 return 0;
790 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000791 SAM("WARNING: failed to adjust saturation to " \
R.M. Thomas702422b2010-06-18 12:29:49 -0700792 "0x%02X\n", mood);
793 return -ENOENT;
794 }
795 break;
R.M. Thomas702422b2010-06-18 12:29:49 -0700796 }
797 i1++;
798}
Mike Thomase68703c2010-11-07 19:58:55 +0000799SAM("WARNING: failed to adjust saturation: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700800return -ENOENT;
801}
802/*****************************************************************************/
803int adjust_hue(struct easycap *peasycap, int value)
804{
805unsigned int mood;
Mike Thomasf36bc372010-11-07 20:00:35 +0000806int i1, i2, k;
R.M. Thomas702422b2010-06-18 12:29:49 -0700807
Mike Thomase68703c2010-11-07 19:58:55 +0000808if (NULL == peasycap) {
809 SAY("ERROR: peasycap is NULL\n");
810 return -EFAULT;
811}
R.M. Thomas702422b2010-06-18 12:29:49 -0700812if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000813 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700814 return -EFAULT;
815}
816i1 = 0;
817while (0xFFFFFFFF != easycap_control[i1].id) {
818 if (V4L2_CID_HUE == easycap_control[i1].id) {
819 if ((easycap_control[i1].minimum > value) || \
820 (easycap_control[i1].maximum < value))
821 value = easycap_control[i1].default_value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000822
823 if ((easycap_control[i1].minimum <= peasycap->hue) && \
824 (easycap_control[i1].maximum >= \
825 peasycap->hue)) {
826 if (peasycap->hue == value) {
827 SAM("unchanged hue at 0x%02X\n", value);
828 return 0;
829 }
830 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700831 peasycap->hue = value;
Mike Thomasf36bc372010-11-07 20:00:35 +0000832 for (k = 0; k < INPUT_MANY; k++) {
833 if (!peasycap->inputset[k].hue_ok)
834 peasycap->inputset[k].hue = peasycap->hue;
835 }
836 if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
837 peasycap->inputset[peasycap->input].hue = \
838 peasycap->hue;
839 peasycap->inputset[peasycap->input].hue_ok = 1;
840 } else
841 JOM(8, "%i=peasycap->input\n", peasycap->input);
R.M. Thomas702422b2010-06-18 12:29:49 -0700842 i2 = peasycap->hue - 128;
843 mood = 0x00FF & ((int) i2);
R.M. Thomas702422b2010-06-18 12:29:49 -0700844 if (!write_saa(peasycap->pusb_device, 0x0D, mood)) {
Mike Thomase68703c2010-11-07 19:58:55 +0000845 SAM("adjusting hue to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700846 return 0;
847 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000848 SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700849 return -ENOENT;
850 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700851 break;
852 }
853 i1++;
854}
Mike Thomase68703c2010-11-07 19:58:55 +0000855SAM("WARNING: failed to adjust hue: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700856return -ENOENT;
857}
858/*****************************************************************************/
859int adjust_volume(struct easycap *peasycap, int value)
860{
861__s8 mood;
862int i1;
863
Mike Thomase68703c2010-11-07 19:58:55 +0000864if (NULL == peasycap) {
865 SAY("ERROR: peasycap is NULL\n");
866 return -EFAULT;
867}
R.M. Thomas702422b2010-06-18 12:29:49 -0700868if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000869 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700870 return -EFAULT;
871}
872i1 = 0;
873while (0xFFFFFFFF != easycap_control[i1].id) {
874 if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
875 if ((easycap_control[i1].minimum > value) || \
Mike Thomas94155cf2010-11-07 20:05:51 +0000876 (easycap_control[i1].maximum < value))
R.M. Thomas702422b2010-06-18 12:29:49 -0700877 value = easycap_control[i1].default_value;
Mike Thomas94155cf2010-11-07 20:05:51 +0000878 if ((easycap_control[i1].minimum <= peasycap->volume) && \
879 (easycap_control[i1].maximum >= \
880 peasycap->volume)) {
881 if (peasycap->volume == value) {
882 SAM("unchanged volume at 0x%02X\n", value);
883 return 0;
884 }
885 }
R.M. Thomas702422b2010-06-18 12:29:49 -0700886 peasycap->volume = value;
887 mood = (16 > peasycap->volume) ? 16 : \
888 ((31 < peasycap->volume) ? 31 : \
889 (__s8) peasycap->volume);
890 if (!audio_gainset(peasycap->pusb_device, mood)) {
Mike Thomas94155cf2010-11-07 20:05:51 +0000891 SAM("adjusting volume to 0x%02X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700892 return 0;
893 } else {
Mike Thomase68703c2010-11-07 19:58:55 +0000894 SAM("WARNING: failed to adjust volume to " \
Mike Thomas94155cf2010-11-07 20:05:51 +0000895 "0x%2X\n", mood);
R.M. Thomas702422b2010-06-18 12:29:49 -0700896 return -ENOENT;
897 }
898 break;
899 }
900i1++;
901}
Mike Thomase68703c2010-11-07 19:58:55 +0000902SAM("WARNING: failed to adjust volume: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700903return -ENOENT;
904}
905/*****************************************************************************/
906/*---------------------------------------------------------------------------*/
907/*
908 * AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
909 * usb_set_interface(peasycap->pusb_device, \
910 * peasycap->audio_interface, \
911 * peasycap->audio_altsetting_off);
912 * HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
913 * -ESHUTDOWN. THE HANDLER ROUTINE easysnd_complete() DECLINES TO RESUBMIT
914 * THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY. BEWARE.
915 */
916/*---------------------------------------------------------------------------*/
917int adjust_mute(struct easycap *peasycap, int value)
918{
919int i1;
920
Mike Thomase68703c2010-11-07 19:58:55 +0000921if (NULL == peasycap) {
922 SAY("ERROR: peasycap is NULL\n");
923 return -EFAULT;
924}
R.M. Thomas702422b2010-06-18 12:29:49 -0700925if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +0000926 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700927 return -EFAULT;
928}
929i1 = 0;
930while (0xFFFFFFFF != easycap_control[i1].id) {
931 if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
932 peasycap->mute = value;
933 switch (peasycap->mute) {
934 case 1: {
935 peasycap->audio_idle = 1;
936 peasycap->timeval0.tv_sec = 0;
Mike Thomase68703c2010-11-07 19:58:55 +0000937 SAM("adjusting mute: %i=peasycap->audio_idle\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700938 peasycap->audio_idle);
939 return 0;
940 }
941 default: {
942 peasycap->audio_idle = 0;
Mike Thomase68703c2010-11-07 19:58:55 +0000943 SAM("adjusting mute: %i=peasycap->audio_idle\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -0700944 peasycap->audio_idle);
945 return 0;
946 }
947 }
948 break;
949 }
950 i1++;
951}
Mike Thomase68703c2010-11-07 19:58:55 +0000952SAM("WARNING: failed to adjust mute: control not found\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700953return -ENOENT;
954}
Mike Thomase68703c2010-11-07 19:58:55 +0000955/*****************************************************************************/
Mike Thomasae59dad2010-11-07 20:09:19 +0000956/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
957#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
958 (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
959long
960easycap_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
961 return (long)easycap_ioctl((struct inode *)NULL, file, cmd, arg);
962}
963#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
964/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
965/*---------------------------------------------------------------------------*/
966int
967easycap_ioctl(struct inode *inode, struct file *file,
968 unsigned int cmd, unsigned long arg)
R.M. Thomas702422b2010-06-18 12:29:49 -0700969{
Mike Thomas2a87a0b2010-11-07 20:07:12 +0000970struct easycap *peasycap;
971struct usb_device *p;
Mike Thomasae59dad2010-11-07 20:09:19 +0000972int kd;
R.M. Thomas702422b2010-06-18 12:29:49 -0700973
Mike Thomase68703c2010-11-07 19:58:55 +0000974if (NULL == file) {
975 SAY("ERROR: file is NULL\n");
976 return -ERESTARTSYS;
977}
Joe Perchesba952d82010-07-12 13:50:10 -0700978peasycap = file->private_data;
R.M. Thomas702422b2010-06-18 12:29:49 -0700979if (NULL == peasycap) {
Mike Thomas268dfed2010-11-07 20:11:36 +0000980 SAY("ERROR: peasycap is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700981 return -1;
982}
Mike Thomas268dfed2010-11-07 20:11:36 +0000983if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
984 SAY("ERROR: bad peasycap\n");
985 return -EFAULT;
986}
R.M. Thomas702422b2010-06-18 12:29:49 -0700987p = peasycap->pusb_device;
Mike Thomase68703c2010-11-07 19:58:55 +0000988if (NULL == p) {
989 SAM("ERROR: peasycap->pusb_device is NULL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -0700990 return -EFAULT;
991}
Mike Thomasae59dad2010-11-07 20:09:19 +0000992kd = isdongle(peasycap);
993if (0 <= kd && DONGLE_MANY > kd) {
994 if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_video)) {
995 SAY("ERROR: cannot lock easycap_dongle[%i].mutex_video\n", kd);
996 return -ERESTARTSYS;
997 }
998 JOM(4, "locked easycap_dongle[%i].mutex_video\n", kd);
999/*---------------------------------------------------------------------------*/
1000/*
1001 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
1002 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
1003 * IF NECESSARY, BAIL OUT.
1004*/
1005/*---------------------------------------------------------------------------*/
1006 if (kd != isdongle(peasycap))
1007 return -ERESTARTSYS;
1008 if (NULL == file) {
1009 SAY("ERROR: file is NULL\n");
1010 mutex_unlock(&easycap_dongle[kd].mutex_video);
1011 return -ERESTARTSYS;
1012 }
1013 peasycap = file->private_data;
1014 if (NULL == peasycap) {
1015 SAY("ERROR: peasycap is NULL\n");
1016 mutex_unlock(&easycap_dongle[kd].mutex_video);
1017 return -ERESTARTSYS;
1018 }
Mike Thomas268dfed2010-11-07 20:11:36 +00001019 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
1020 SAY("ERROR: bad peasycap\n");
1021 mutex_unlock(&easycap_dongle[kd].mutex_video);
1022 return -EFAULT;
1023 }
Mike Thomasae59dad2010-11-07 20:09:19 +00001024 p = peasycap->pusb_device;
1025 if (NULL == peasycap->pusb_device) {
1026 SAM("ERROR: peasycap->pusb_device is NULL\n");
1027 mutex_unlock(&easycap_dongle[kd].mutex_video);
1028 return -ERESTARTSYS;
1029 }
1030} else {
1031/*---------------------------------------------------------------------------*/
1032/*
1033 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
1034 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
1035*/
1036/*---------------------------------------------------------------------------*/
1037 return -ERESTARTSYS;
1038}
R.M. Thomas702422b2010-06-18 12:29:49 -07001039/*---------------------------------------------------------------------------*/
R.M. Thomas702422b2010-06-18 12:29:49 -07001040switch (cmd) {
1041case VIDIOC_QUERYCAP: {
Mike Thomase68703c2010-11-07 19:58:55 +00001042 struct v4l2_capability v4l2_capability;
1043 char version[16], *p1, *p2;
1044 int i, rc, k[3];
1045 long lng;
R.M. Thomas702422b2010-06-18 12:29:49 -07001046
Mike Thomase68703c2010-11-07 19:58:55 +00001047 JOM(8, "VIDIOC_QUERYCAP\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001048
1049 if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
Mike Thomasae59dad2010-11-07 20:09:19 +00001050 SAM("ERROR: bad driver version string\n");
1051 mutex_unlock(&easycap_dongle[kd].mutex_video);
1052 return -EINVAL;
R.M. Thomas702422b2010-06-18 12:29:49 -07001053 }
1054 strcpy(&version[0], EASYCAP_DRIVER_VERSION);
1055 for (i = 0; i < 3; i++)
1056 k[i] = 0;
1057 p2 = &version[0]; i = 0;
1058 while (*p2) {
1059 p1 = p2;
1060 while (*p2 && ('.' != *p2))
1061 p2++;
1062 if (*p2)
1063 *p2++ = 0;
1064 if (3 > i) {
1065 rc = (int) strict_strtol(p1, 10, &lng);
1066 if (0 != rc) {
Mike Thomase68703c2010-11-07 19:58:55 +00001067 SAM("ERROR: %i=strict_strtol(%s,.,,)\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07001068 rc, p1);
Mike Thomasae59dad2010-11-07 20:09:19 +00001069 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001070 return -EINVAL;
1071 }
1072 k[i] = (int)lng;
1073 }
1074 i++;
1075 }
1076
1077 memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
1078 strlcpy(&v4l2_capability.driver[0], "easycap", \
1079 sizeof(v4l2_capability.driver));
1080
1081 v4l2_capability.capabilities = \
1082 V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
1083 V4L2_CAP_AUDIO | V4L2_CAP_READWRITE;
1084
1085 v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
Mike Thomase68703c2010-11-07 19:58:55 +00001086 JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001087
1088 strlcpy(&v4l2_capability.card[0], "EasyCAP DC60", \
1089 sizeof(v4l2_capability.card));
1090
1091 if (usb_make_path(peasycap->pusb_device, &v4l2_capability.bus_info[0],\
1092 sizeof(v4l2_capability.bus_info)) < 0) {
1093 strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info", \
1094 sizeof(v4l2_capability.bus_info));
Mike Thomase68703c2010-11-07 19:58:55 +00001095 JOM(8, "%s=v4l2_capability.bus_info\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07001096 &v4l2_capability.bus_info[0]);
1097 }
1098 if (0 != copy_to_user((void __user *)arg, &v4l2_capability, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001099 sizeof(struct v4l2_capability))) {
1100 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001101 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001102 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001103 break;
1104}
1105/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1106case VIDIOC_ENUMINPUT: {
Mike Thomase68703c2010-11-07 19:58:55 +00001107 struct v4l2_input v4l2_input;
1108 __u32 index;
R.M. Thomas702422b2010-06-18 12:29:49 -07001109
Mike Thomase68703c2010-11-07 19:58:55 +00001110 JOM(8, "VIDIOC_ENUMINPUT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001111
1112 if (0 != copy_from_user(&v4l2_input, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001113 sizeof(struct v4l2_input))) {
1114 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001115 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001116 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001117
1118 index = v4l2_input.index;
1119 memset(&v4l2_input, 0, sizeof(struct v4l2_input));
1120
1121 switch (index) {
1122 case 0: {
1123 v4l2_input.index = index;
1124 strcpy(&v4l2_input.name[0], "CVBS0");
1125 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1126 v4l2_input.audioset = 0x01;
1127 v4l2_input.tuner = 0;
1128 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1129 V4L2_STD_NTSC ;
1130 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001131 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001132 break;
1133 }
1134 case 1: {
1135 v4l2_input.index = index;
1136 strcpy(&v4l2_input.name[0], "CVBS1");
1137 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1138 v4l2_input.audioset = 0x01;
1139 v4l2_input.tuner = 0;
1140 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1141 V4L2_STD_NTSC ;
1142 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001143 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001144 break;
1145 }
1146 case 2: {
1147 v4l2_input.index = index;
1148 strcpy(&v4l2_input.name[0], "CVBS2");
1149 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1150 v4l2_input.audioset = 0x01;
1151 v4l2_input.tuner = 0;
1152 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1153 V4L2_STD_NTSC ;
1154 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001155 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001156 break;
1157 }
1158 case 3: {
1159 v4l2_input.index = index;
1160 strcpy(&v4l2_input.name[0], "CVBS3");
1161 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1162 v4l2_input.audioset = 0x01;
1163 v4l2_input.tuner = 0;
1164 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1165 V4L2_STD_NTSC ;
1166 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001167 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001168 break;
1169 }
1170 case 4: {
1171 v4l2_input.index = index;
1172 strcpy(&v4l2_input.name[0], "CVBS4");
1173 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1174 v4l2_input.audioset = 0x01;
1175 v4l2_input.tuner = 0;
1176 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1177 V4L2_STD_NTSC ;
1178 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001179 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001180 break;
1181 }
1182 case 5: {
1183 v4l2_input.index = index;
1184 strcpy(&v4l2_input.name[0], "S-VIDEO");
1185 v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
1186 v4l2_input.audioset = 0x01;
1187 v4l2_input.tuner = 0;
1188 v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM | \
1189 V4L2_STD_NTSC ;
1190 v4l2_input.status = 0;
Mike Thomase68703c2010-11-07 19:58:55 +00001191 JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001192 break;
1193 }
1194 default: {
Mike Thomase68703c2010-11-07 19:58:55 +00001195 JOM(8, "%i=index: exhausts inputs\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001196 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001197 return -EINVAL;
1198 }
1199 }
1200
1201 if (0 != copy_to_user((void __user *)arg, &v4l2_input, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001202 sizeof(struct v4l2_input))) {
1203 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001204 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001205 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001206 break;
1207}
1208/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1209case VIDIOC_G_INPUT: {
Mike Thomase68703c2010-11-07 19:58:55 +00001210 __u32 index;
R.M. Thomas702422b2010-06-18 12:29:49 -07001211
Mike Thomase68703c2010-11-07 19:58:55 +00001212 JOM(8, "VIDIOC_G_INPUT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001213 index = (__u32)peasycap->input;
Mike Thomase68703c2010-11-07 19:58:55 +00001214 JOM(8, "user is told: %i\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001215 if (0 != copy_to_user((void __user *)arg, &index, sizeof(__u32))) {
1216 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001217 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001218 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001219 break;
1220}
1221/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1222case VIDIOC_S_INPUT:
1223 {
Mike Thomase68703c2010-11-07 19:58:55 +00001224 __u32 index;
Mike Thomasf36bc372010-11-07 20:00:35 +00001225 int rc;
R.M. Thomas702422b2010-06-18 12:29:49 -07001226
Mike Thomase68703c2010-11-07 19:58:55 +00001227 JOM(8, "VIDIOC_S_INPUT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001228
Mike Thomasae59dad2010-11-07 20:09:19 +00001229 if (0 != copy_from_user(&index, (void __user *)arg, sizeof(__u32))) {
1230 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001231 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001232 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001233
Mike Thomase68703c2010-11-07 19:58:55 +00001234 JOM(8, "user requests input %i\n", index);
R.M. Thomas702422b2010-06-18 12:29:49 -07001235
1236 if ((int)index == peasycap->input) {
Mike Thomase68703c2010-11-07 19:58:55 +00001237 SAM("requested input already in effect\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001238 break;
1239 }
1240
Mike Thomasf36bc372010-11-07 20:00:35 +00001241 if ((0 > index) || (INPUT_MANY <= index)) {
Mike Thomase68703c2010-11-07 19:58:55 +00001242 JOM(8, "ERROR: bad requested input: %i\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001243 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001244 return -EINVAL;
1245 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001246
Mike Thomasf36bc372010-11-07 20:00:35 +00001247 rc = newinput(peasycap, (int)index);
1248 if (0 == rc) {
1249 JOM(8, "newinput(.,%i) OK\n", (int)index);
1250 } else {
1251 SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
Mike Thomasae59dad2010-11-07 20:09:19 +00001252 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasf36bc372010-11-07 20:00:35 +00001253 return -EFAULT;
1254 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001255 break;
1256}
1257/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1258case VIDIOC_ENUMAUDIO: {
Mike Thomase68703c2010-11-07 19:58:55 +00001259 JOM(8, "VIDIOC_ENUMAUDIO\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001260 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001261 return -EINVAL;
1262}
1263/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1264case VIDIOC_ENUMAUDOUT: {
Mike Thomase68703c2010-11-07 19:58:55 +00001265 struct v4l2_audioout v4l2_audioout;
R.M. Thomas702422b2010-06-18 12:29:49 -07001266
Mike Thomase68703c2010-11-07 19:58:55 +00001267 JOM(8, "VIDIOC_ENUMAUDOUT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001268
1269 if (0 != copy_from_user(&v4l2_audioout, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001270 sizeof(struct v4l2_audioout))) {
1271 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001272 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001273 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001274
Mike Thomasae59dad2010-11-07 20:09:19 +00001275 if (0 != v4l2_audioout.index) {
1276 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001277 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00001278 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001279 memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
1280 v4l2_audioout.index = 0;
1281 strcpy(&v4l2_audioout.name[0], "Soundtrack");
1282
1283 if (0 != copy_to_user((void __user *)arg, &v4l2_audioout, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001284 sizeof(struct v4l2_audioout))) {
1285 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001286 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001287 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001288 break;
1289}
1290/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1291case VIDIOC_QUERYCTRL: {
Mike Thomase68703c2010-11-07 19:58:55 +00001292 int i1;
1293 struct v4l2_queryctrl v4l2_queryctrl;
R.M. Thomas702422b2010-06-18 12:29:49 -07001294
Mike Thomase68703c2010-11-07 19:58:55 +00001295 JOM(8, "VIDIOC_QUERYCTRL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001296
1297 if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001298 sizeof(struct v4l2_queryctrl))) {
1299 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001300 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001301 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001302
1303 i1 = 0;
1304 while (0xFFFFFFFF != easycap_control[i1].id) {
1305 if (easycap_control[i1].id == v4l2_queryctrl.id) {
Mike Thomase68703c2010-11-07 19:58:55 +00001306 JOM(8, "VIDIOC_QUERYCTRL %s=easycap_control[%i]" \
R.M. Thomas702422b2010-06-18 12:29:49 -07001307 ".name\n", &easycap_control[i1].name[0], i1);
1308 memcpy(&v4l2_queryctrl, &easycap_control[i1], \
1309 sizeof(struct v4l2_queryctrl));
1310 break;
1311 }
1312 i1++;
1313 }
1314 if (0xFFFFFFFF == easycap_control[i1].id) {
Mike Thomase68703c2010-11-07 19:58:55 +00001315 JOM(8, "%i=index: exhausts controls\n", i1);
Mike Thomasae59dad2010-11-07 20:09:19 +00001316 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001317 return -EINVAL;
1318 }
1319 if (0 != copy_to_user((void __user *)arg, &v4l2_queryctrl, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001320 sizeof(struct v4l2_queryctrl))) {
1321 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001322 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001323 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001324 break;
1325}
1326/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1327case VIDIOC_QUERYMENU: {
Mike Thomase68703c2010-11-07 19:58:55 +00001328 JOM(8, "VIDIOC_QUERYMENU unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001329 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001330 return -EINVAL;
R.M. Thomas702422b2010-06-18 12:29:49 -07001331}
1332/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1333case VIDIOC_G_CTRL: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001334 struct v4l2_control *pv4l2_control;
R.M. Thomas702422b2010-06-18 12:29:49 -07001335
Mike Thomase68703c2010-11-07 19:58:55 +00001336 JOM(8, "VIDIOC_G_CTRL\n");
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001337 pv4l2_control = kzalloc(sizeof(struct v4l2_control), GFP_KERNEL);
1338 if (!pv4l2_control) {
1339 SAM("ERROR: out of memory\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001340 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001341 return -ENOMEM;
1342 }
1343 if (0 != copy_from_user(pv4l2_control, (void __user *)arg, \
1344 sizeof(struct v4l2_control))) {
1345 kfree(pv4l2_control);
Mike Thomasae59dad2010-11-07 20:09:19 +00001346 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001347 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001348 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001349
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001350 switch (pv4l2_control->id) {
R.M. Thomas702422b2010-06-18 12:29:49 -07001351 case V4L2_CID_BRIGHTNESS: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001352 pv4l2_control->value = peasycap->brightness;
1353 JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001354 break;
1355 }
1356 case V4L2_CID_CONTRAST: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001357 pv4l2_control->value = peasycap->contrast;
1358 JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001359 break;
1360 }
1361 case V4L2_CID_SATURATION: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001362 pv4l2_control->value = peasycap->saturation;
1363 JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001364 break;
1365 }
1366 case V4L2_CID_HUE: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001367 pv4l2_control->value = peasycap->hue;
1368 JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001369 break;
1370 }
1371 case V4L2_CID_AUDIO_VOLUME: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001372 pv4l2_control->value = peasycap->volume;
1373 JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001374 break;
1375 }
1376 case V4L2_CID_AUDIO_MUTE: {
1377 if (1 == peasycap->mute)
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001378 pv4l2_control->value = true;
R.M. Thomas702422b2010-06-18 12:29:49 -07001379 else
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001380 pv4l2_control->value = false;
1381 JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001382 break;
1383 }
1384 default: {
Mike Thomase68703c2010-11-07 19:58:55 +00001385 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001386 pv4l2_control->id);
1387 kfree(pv4l2_control);
Mike Thomasae59dad2010-11-07 20:09:19 +00001388 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001389 return -EINVAL;
1390 }
1391 }
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001392 if (0 != copy_to_user((void __user *)arg, pv4l2_control, \
1393 sizeof(struct v4l2_control))) {
1394 kfree(pv4l2_control);
Mike Thomasae59dad2010-11-07 20:09:19 +00001395 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001396 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001397 }
1398 kfree(pv4l2_control);
R.M. Thomas702422b2010-06-18 12:29:49 -07001399 break;
1400}
1401/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1402#if defined(VIDIOC_S_CTRL_OLD)
1403case VIDIOC_S_CTRL_OLD: {
Mike Thomase68703c2010-11-07 19:58:55 +00001404 JOM(8, "VIDIOC_S_CTRL_OLD required at least for xawtv\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001405}
1406#endif /*VIDIOC_S_CTRL_OLD*/
1407case VIDIOC_S_CTRL:
1408 {
Mike Thomase68703c2010-11-07 19:58:55 +00001409 struct v4l2_control v4l2_control;
R.M. Thomas702422b2010-06-18 12:29:49 -07001410
Mike Thomase68703c2010-11-07 19:58:55 +00001411 JOM(8, "VIDIOC_S_CTRL\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001412
1413 if (0 != copy_from_user(&v4l2_control, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001414 sizeof(struct v4l2_control))) {
1415 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001416 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001417 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001418
1419 switch (v4l2_control.id) {
1420 case V4L2_CID_BRIGHTNESS: {
Mike Thomase68703c2010-11-07 19:58:55 +00001421 JOM(8, "user requests brightness %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001422 if (0 != adjust_brightness(peasycap, v4l2_control.value))
1423 ;
1424 break;
1425 }
1426 case V4L2_CID_CONTRAST: {
Mike Thomase68703c2010-11-07 19:58:55 +00001427 JOM(8, "user requests contrast %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001428 if (0 != adjust_contrast(peasycap, v4l2_control.value))
1429 ;
1430 break;
1431 }
1432 case V4L2_CID_SATURATION: {
Mike Thomase68703c2010-11-07 19:58:55 +00001433 JOM(8, "user requests saturation %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001434 if (0 != adjust_saturation(peasycap, v4l2_control.value))
1435 ;
1436 break;
1437 }
1438 case V4L2_CID_HUE: {
Mike Thomase68703c2010-11-07 19:58:55 +00001439 JOM(8, "user requests hue %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001440 if (0 != adjust_hue(peasycap, v4l2_control.value))
1441 ;
1442 break;
1443 }
1444 case V4L2_CID_AUDIO_VOLUME: {
Mike Thomase68703c2010-11-07 19:58:55 +00001445 JOM(8, "user requests volume %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001446 if (0 != adjust_volume(peasycap, v4l2_control.value))
1447 ;
1448 break;
1449 }
1450 case V4L2_CID_AUDIO_MUTE: {
1451 int mute;
1452
Mike Thomase68703c2010-11-07 19:58:55 +00001453 JOM(8, "user requests mute %i\n", v4l2_control.value);
R.M. Thomas702422b2010-06-18 12:29:49 -07001454 if (true == v4l2_control.value)
1455 mute = 1;
1456 else
1457 mute = 0;
1458
1459 if (0 != adjust_mute(peasycap, mute))
Mike Thomase68703c2010-11-07 19:58:55 +00001460 SAM("WARNING: failed to adjust mute to %i\n", mute);
R.M. Thomas702422b2010-06-18 12:29:49 -07001461 break;
1462 }
1463 default: {
Mike Thomase68703c2010-11-07 19:58:55 +00001464 SAM("ERROR: unknown V4L2 control: 0x%08X=id\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07001465 v4l2_control.id);
Mike Thomasae59dad2010-11-07 20:09:19 +00001466 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasce36ced2010-11-07 19:56:40 +00001467 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00001468 }
Mike Thomasce36ced2010-11-07 19:56:40 +00001469 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001470 break;
1471}
1472/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1473case VIDIOC_S_EXT_CTRLS: {
Mike Thomase68703c2010-11-07 19:58:55 +00001474 JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001475 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001476 return -EINVAL;
1477}
1478/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1479case VIDIOC_ENUM_FMT: {
Mike Thomase68703c2010-11-07 19:58:55 +00001480 __u32 index;
1481 struct v4l2_fmtdesc v4l2_fmtdesc;
R.M. Thomas702422b2010-06-18 12:29:49 -07001482
Mike Thomase68703c2010-11-07 19:58:55 +00001483 JOM(8, "VIDIOC_ENUM_FMT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001484
1485 if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001486 sizeof(struct v4l2_fmtdesc))) {
1487 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001488 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001489 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001490
1491 index = v4l2_fmtdesc.index;
1492 memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
1493
1494 v4l2_fmtdesc.index = index;
1495 v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1496
1497 switch (index) {
1498 case 0: {
1499 v4l2_fmtdesc.flags = 0;
1500 strcpy(&v4l2_fmtdesc.description[0], "uyvy");
1501 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
Mike Thomase68703c2010-11-07 19:58:55 +00001502 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001503 break;
1504 }
1505 case 1: {
1506 v4l2_fmtdesc.flags = 0;
1507 strcpy(&v4l2_fmtdesc.description[0], "yuy2");
1508 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
Mike Thomase68703c2010-11-07 19:58:55 +00001509 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001510 break;
1511 }
1512 case 2: {
1513 v4l2_fmtdesc.flags = 0;
1514 strcpy(&v4l2_fmtdesc.description[0], "rgb24");
1515 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
Mike Thomase68703c2010-11-07 19:58:55 +00001516 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001517 break;
1518 }
1519 case 3: {
1520 v4l2_fmtdesc.flags = 0;
1521 strcpy(&v4l2_fmtdesc.description[0], "rgb32");
1522 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
Mike Thomase68703c2010-11-07 19:58:55 +00001523 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001524 break;
1525 }
1526 case 4: {
1527 v4l2_fmtdesc.flags = 0;
1528 strcpy(&v4l2_fmtdesc.description[0], "bgr24");
1529 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
Mike Thomase68703c2010-11-07 19:58:55 +00001530 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001531 break;
1532 }
1533 case 5: {
1534 v4l2_fmtdesc.flags = 0;
1535 strcpy(&v4l2_fmtdesc.description[0], "bgr32");
1536 v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
Mike Thomase68703c2010-11-07 19:58:55 +00001537 JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001538 break;
1539 }
1540 default: {
Mike Thomase68703c2010-11-07 19:58:55 +00001541 JOM(8, "%i=index: exhausts formats\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001542 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001543 return -EINVAL;
1544 }
1545 }
1546 if (0 != copy_to_user((void __user *)arg, &v4l2_fmtdesc, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001547 sizeof(struct v4l2_fmtdesc))) {
1548 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001549 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001550 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001551 break;
1552}
1553/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Mike Thomas40b8d502010-11-07 20:02:15 +00001554/*
1555 * THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
1556 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1557*/
1558/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
R.M. Thomas702422b2010-06-18 12:29:49 -07001559case VIDIOC_ENUM_FRAMESIZES: {
Mike Thomas40b8d502010-11-07 20:02:15 +00001560 __u32 index;
1561 struct v4l2_frmsizeenum v4l2_frmsizeenum;
1562
1563 JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
1564
1565 if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001566 sizeof(struct v4l2_frmsizeenum))) {
1567 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001568 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001569 }
Mike Thomas40b8d502010-11-07 20:02:15 +00001570
1571 index = v4l2_frmsizeenum.index;
1572
1573 v4l2_frmsizeenum.type = (__u32) V4L2_FRMSIZE_TYPE_DISCRETE;
1574
1575 if (true == peasycap->ntsc) {
1576 switch (index) {
1577 case 0: {
1578 v4l2_frmsizeenum.discrete.width = 640;
1579 v4l2_frmsizeenum.discrete.height = 480;
1580 JOM(8, "%i=index: %ix%i\n", index, \
1581 (int)(v4l2_frmsizeenum.\
1582 discrete.width), \
1583 (int)(v4l2_frmsizeenum.\
1584 discrete.height));
1585 break;
1586 }
1587 case 1: {
1588 v4l2_frmsizeenum.discrete.width = 320;
1589 v4l2_frmsizeenum.discrete.height = 240;
1590 JOM(8, "%i=index: %ix%i\n", index, \
1591 (int)(v4l2_frmsizeenum.\
1592 discrete.width), \
1593 (int)(v4l2_frmsizeenum.\
1594 discrete.height));
1595 break;
1596 }
1597 case 2: {
1598 v4l2_frmsizeenum.discrete.width = 720;
1599 v4l2_frmsizeenum.discrete.height = 480;
1600 JOM(8, "%i=index: %ix%i\n", index, \
1601 (int)(v4l2_frmsizeenum.\
1602 discrete.width), \
1603 (int)(v4l2_frmsizeenum.\
1604 discrete.height));
1605 break;
1606 }
1607 case 3: {
1608 v4l2_frmsizeenum.discrete.width = 360;
1609 v4l2_frmsizeenum.discrete.height = 240;
1610 JOM(8, "%i=index: %ix%i\n", index, \
1611 (int)(v4l2_frmsizeenum.\
1612 discrete.width), \
1613 (int)(v4l2_frmsizeenum.\
1614 discrete.height));
1615 break;
1616 }
1617 default: {
1618 JOM(8, "%i=index: exhausts framesizes\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001619 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001620 return -EINVAL;
1621 }
1622 }
1623 } else {
1624 switch (index) {
1625 case 0: {
1626 v4l2_frmsizeenum.discrete.width = 640;
1627 v4l2_frmsizeenum.discrete.height = 480;
1628 JOM(8, "%i=index: %ix%i\n", index, \
1629 (int)(v4l2_frmsizeenum.\
1630 discrete.width), \
1631 (int)(v4l2_frmsizeenum.\
1632 discrete.height));
1633 break;
1634 }
1635 case 1: {
1636 v4l2_frmsizeenum.discrete.width = 320;
1637 v4l2_frmsizeenum.discrete.height = 240;
1638 JOM(8, "%i=index: %ix%i\n", index, \
1639 (int)(v4l2_frmsizeenum.\
1640 discrete.width), \
1641 (int)(v4l2_frmsizeenum.\
1642 discrete.height));
1643 break;
1644 }
1645 case 2: {
1646 v4l2_frmsizeenum.discrete.width = 704;
1647 v4l2_frmsizeenum.discrete.height = 576;
1648 JOM(8, "%i=index: %ix%i\n", index, \
1649 (int)(v4l2_frmsizeenum.\
1650 discrete.width), \
1651 (int)(v4l2_frmsizeenum.\
1652 discrete.height));
1653 break;
1654 }
1655 case 3: {
1656 v4l2_frmsizeenum.discrete.width = 720;
1657 v4l2_frmsizeenum.discrete.height = 576;
1658 JOM(8, "%i=index: %ix%i\n", index, \
1659 (int)(v4l2_frmsizeenum.\
1660 discrete.width), \
1661 (int)(v4l2_frmsizeenum.\
1662 discrete.height));
1663 break;
1664 }
1665 case 4: {
1666 v4l2_frmsizeenum.discrete.width = 360;
1667 v4l2_frmsizeenum.discrete.height = 288;
1668 JOM(8, "%i=index: %ix%i\n", index, \
1669 (int)(v4l2_frmsizeenum.\
1670 discrete.width), \
1671 (int)(v4l2_frmsizeenum.\
1672 discrete.height));
1673 break;
1674 }
1675 default: {
1676 JOM(8, "%i=index: exhausts framesizes\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001677 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001678 return -EINVAL;
1679 }
1680 }
1681 }
1682 if (0 != copy_to_user((void __user *)arg, &v4l2_frmsizeenum, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001683 sizeof(struct v4l2_frmsizeenum))) {
1684 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001685 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001686 }
Mike Thomas40b8d502010-11-07 20:02:15 +00001687 break;
R.M. Thomas702422b2010-06-18 12:29:49 -07001688}
Mike Thomas40b8d502010-11-07 20:02:15 +00001689/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1690/*
1691 * THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
1692 * THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS. BEWARE.
1693*/
1694/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
R.M. Thomas702422b2010-06-18 12:29:49 -07001695case VIDIOC_ENUM_FRAMEINTERVALS: {
Mike Thomas40b8d502010-11-07 20:02:15 +00001696 __u32 index;
1697 int denominator;
1698 struct v4l2_frmivalenum v4l2_frmivalenum;
1699
1700 JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
1701
1702 if (peasycap->fps)
1703 denominator = peasycap->fps;
1704 else {
1705 if (true == peasycap->ntsc)
1706 denominator = 30;
1707 else
1708 denominator = 25;
1709 }
1710
1711 if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg, \
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001712 sizeof(struct v4l2_frmivalenum))) {
Mike Thomasae59dad2010-11-07 20:09:19 +00001713 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001714 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001715 }
Mike Thomas40b8d502010-11-07 20:02:15 +00001716
1717 index = v4l2_frmivalenum.index;
1718
1719 v4l2_frmivalenum.type = (__u32) V4L2_FRMIVAL_TYPE_DISCRETE;
1720
1721 switch (index) {
1722 case 0: {
1723 v4l2_frmivalenum.discrete.numerator = 1;
1724 v4l2_frmivalenum.discrete.denominator = denominator;
1725 JOM(8, "%i=index: %i/%i\n", index, \
1726 (int)(v4l2_frmivalenum.discrete.numerator), \
1727 (int)(v4l2_frmivalenum.discrete.denominator));
1728 break;
1729 }
1730 case 1: {
1731 v4l2_frmivalenum.discrete.numerator = 1;
1732 v4l2_frmivalenum.discrete.denominator = denominator/5;
1733 JOM(8, "%i=index: %i/%i\n", index, \
1734 (int)(v4l2_frmivalenum.discrete.numerator), \
1735 (int)(v4l2_frmivalenum.discrete.denominator));
1736 break;
1737 }
1738 default: {
1739 JOM(8, "%i=index: exhausts frameintervals\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001740 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001741 return -EINVAL;
1742 }
1743 }
1744 if (0 != copy_to_user((void __user *)arg, &v4l2_frmivalenum, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001745 sizeof(struct v4l2_frmivalenum))) {
1746 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas40b8d502010-11-07 20:02:15 +00001747 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001748 }
Mike Thomas40b8d502010-11-07 20:02:15 +00001749 break;
R.M. Thomas702422b2010-06-18 12:29:49 -07001750}
1751/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1752case VIDIOC_G_FMT: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001753 struct v4l2_format *pv4l2_format;
1754 struct v4l2_pix_format *pv4l2_pix_format;
R.M. Thomas702422b2010-06-18 12:29:49 -07001755
Mike Thomase68703c2010-11-07 19:58:55 +00001756 JOM(8, "VIDIOC_G_FMT\n");
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001757 pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
1758 if (!pv4l2_format) {
1759 SAM("ERROR: out of memory\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001760 mutex_unlock(&easycap_dongle[kd].mutex_video);
1761 return -ENOMEM;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001762 }
1763 pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
1764 if (!pv4l2_pix_format) {
1765 SAM("ERROR: out of memory\n");
1766 kfree(pv4l2_format);
Mike Thomasae59dad2010-11-07 20:09:19 +00001767 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001768 return -ENOMEM;
1769 }
1770 if (0 != copy_from_user(pv4l2_format, (void __user *)arg, \
1771 sizeof(struct v4l2_format))) {
1772 kfree(pv4l2_format);
1773 kfree(pv4l2_pix_format);
Mike Thomasae59dad2010-11-07 20:09:19 +00001774 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001775 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001776 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001777
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001778 if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1779 kfree(pv4l2_format);
1780 kfree(pv4l2_pix_format);
Mike Thomasae59dad2010-11-07 20:09:19 +00001781 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001782 return -EINVAL;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001783 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001784
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001785 memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1786 pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1787 memcpy(&pv4l2_format->fmt.pix, \
1788 &easycap_format[peasycap->format_offset]\
1789 .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
Mike Thomase68703c2010-11-07 19:58:55 +00001790 JOM(8, "user is told: %s\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07001791 &easycap_format[peasycap->format_offset].name[0]);
1792
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001793 if (0 != copy_to_user((void __user *)arg, pv4l2_format, \
1794 sizeof(struct v4l2_format))) {
1795 kfree(pv4l2_format);
1796 kfree(pv4l2_pix_format);
Mike Thomasae59dad2010-11-07 20:09:19 +00001797 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001798 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00001799 }
1800 kfree(pv4l2_format);
1801 kfree(pv4l2_pix_format);
R.M. Thomas702422b2010-06-18 12:29:49 -07001802 break;
1803}
1804/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1805case VIDIOC_TRY_FMT:
1806case VIDIOC_S_FMT: {
Mike Thomase68703c2010-11-07 19:58:55 +00001807 struct v4l2_format v4l2_format;
1808 struct v4l2_pix_format v4l2_pix_format;
1809 bool try;
1810 int best_format;
R.M. Thomas702422b2010-06-18 12:29:49 -07001811
1812 if (VIDIOC_TRY_FMT == cmd) {
Mike Thomase68703c2010-11-07 19:58:55 +00001813 JOM(8, "VIDIOC_TRY_FMT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001814 try = true;
1815 } else {
Mike Thomase68703c2010-11-07 19:58:55 +00001816 JOM(8, "VIDIOC_S_FMT\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001817 try = false;
1818 }
1819
1820 if (0 != copy_from_user(&v4l2_format, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001821 sizeof(struct v4l2_format))) {
1822 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001823 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001824 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001825
1826 best_format = adjust_format(peasycap, \
1827 v4l2_format.fmt.pix.width, \
1828 v4l2_format.fmt.pix.height, \
1829 v4l2_format.fmt.pix.pixelformat, \
1830 v4l2_format.fmt.pix.field, \
1831 try);
1832 if (0 > best_format) {
Mike Thomasae59dad2010-11-07 20:09:19 +00001833 if (-EBUSY == best_format) {
1834 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasf36bc372010-11-07 20:00:35 +00001835 return -EBUSY;
Mike Thomasae59dad2010-11-07 20:09:19 +00001836 }
Mike Thomase68703c2010-11-07 19:58:55 +00001837 JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
Mike Thomasae59dad2010-11-07 20:09:19 +00001838 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001839 return -ENOENT;
1840 }
1841/*...........................................................................*/
1842 memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
1843 v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1844
1845 memcpy(&(v4l2_format.fmt.pix), &(easycap_format[best_format]\
1846 .v4l2_format.fmt.pix), sizeof(v4l2_pix_format));
Mike Thomase68703c2010-11-07 19:58:55 +00001847 JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
R.M. Thomas702422b2010-06-18 12:29:49 -07001848
1849 if (0 != copy_to_user((void __user *)arg, &v4l2_format, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001850 sizeof(struct v4l2_format))) {
1851 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001852 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001853 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001854 break;
1855}
1856/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1857case VIDIOC_CROPCAP: {
Mike Thomase68703c2010-11-07 19:58:55 +00001858 struct v4l2_cropcap v4l2_cropcap;
R.M. Thomas702422b2010-06-18 12:29:49 -07001859
Mike Thomase68703c2010-11-07 19:58:55 +00001860 JOM(8, "VIDIOC_CROPCAP\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001861
1862 if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001863 sizeof(struct v4l2_cropcap))) {
1864 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001865 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001866 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001867
1868 if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Mike Thomase68703c2010-11-07 19:58:55 +00001869 JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001870
1871 memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
1872 v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1873 v4l2_cropcap.bounds.left = 0;
1874 v4l2_cropcap.bounds.top = 0;
1875 v4l2_cropcap.bounds.width = peasycap->width;
1876 v4l2_cropcap.bounds.height = peasycap->height;
1877 v4l2_cropcap.defrect.left = 0;
1878 v4l2_cropcap.defrect.top = 0;
1879 v4l2_cropcap.defrect.width = peasycap->width;
1880 v4l2_cropcap.defrect.height = peasycap->height;
1881 v4l2_cropcap.pixelaspect.numerator = 1;
1882 v4l2_cropcap.pixelaspect.denominator = 1;
1883
Mike Thomase68703c2010-11-07 19:58:55 +00001884 JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
R.M. Thomas702422b2010-06-18 12:29:49 -07001885
1886 if (0 != copy_to_user((void __user *)arg, &v4l2_cropcap, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001887 sizeof(struct v4l2_cropcap))) {
1888 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001889 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001890 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001891 break;
1892}
1893/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1894case VIDIOC_G_CROP:
1895case VIDIOC_S_CROP: {
Mike Thomase68703c2010-11-07 19:58:55 +00001896 JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001897 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001898 return -EINVAL;
1899}
1900/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1901case VIDIOC_QUERYSTD: {
Mike Thomase68703c2010-11-07 19:58:55 +00001902 JOM(8, "VIDIOC_QUERYSTD: " \
R.M. Thomas702422b2010-06-18 12:29:49 -07001903 "EasyCAP is incapable of detecting standard\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00001904 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001905 return -EINVAL;
1906 break;
1907}
1908/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1909/*---------------------------------------------------------------------------*/
1910/*
1911 * THE MANIPULATIONS INVOLVING last0,last1,last2,last3 CONSTITUTE A WORKAROUND
1912 * FOR WHAT APPEARS TO BE A BUG IN 64-BIT mplayer.
1913 * NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
1914 */
1915/*---------------------------------------------------------------------------*/
1916case VIDIOC_ENUMSTD: {
Mike Thomase68703c2010-11-07 19:58:55 +00001917 int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
1918 struct v4l2_standard v4l2_standard;
1919 __u32 index;
1920 struct easycap_standard const *peasycap_standard;
R.M. Thomas702422b2010-06-18 12:29:49 -07001921
Mike Thomase68703c2010-11-07 19:58:55 +00001922 JOM(8, "VIDIOC_ENUMSTD\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001923
1924 if (0 != copy_from_user(&v4l2_standard, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001925 sizeof(struct v4l2_standard))) {
1926 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001927 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001928 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001929 index = v4l2_standard.index;
1930
1931 last3 = last2; last2 = last1; last1 = last0; last0 = index;
1932 if ((index == last3) && (index == last2) && \
1933 (index == last1) && (index == last0)) {
1934 index++;
1935 last3 = last2; last2 = last1; last1 = last0; last0 = index;
1936 }
1937
1938 memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
1939
1940 peasycap_standard = &easycap_standard[0];
1941 while (0xFFFF != peasycap_standard->mask) {
1942 if ((int)(peasycap_standard - &easycap_standard[0]) == index)
1943 break;
1944 peasycap_standard++;
1945 }
1946 if (0xFFFF == peasycap_standard->mask) {
Mike Thomase68703c2010-11-07 19:58:55 +00001947 JOM(8, "%i=index: exhausts standards\n", index);
Mike Thomasae59dad2010-11-07 20:09:19 +00001948 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001949 return -EINVAL;
1950 }
Mike Thomase68703c2010-11-07 19:58:55 +00001951 JOM(8, "%i=index: %s\n", index, \
R.M. Thomas702422b2010-06-18 12:29:49 -07001952 &(peasycap_standard->v4l2_standard.name[0]));
Mike Thomas3d423e92010-07-11 10:51:13 +01001953 memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard), \
1954 sizeof(struct v4l2_standard));
1955
R.M. Thomas702422b2010-06-18 12:29:49 -07001956 v4l2_standard.index = index;
1957
Mike Thomas3d423e92010-07-11 10:51:13 +01001958 if (0 != copy_to_user((void __user *)arg, &v4l2_standard, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001959 sizeof(struct v4l2_standard))) {
1960 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001961 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001962 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001963 break;
1964}
1965/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1966case VIDIOC_G_STD: {
Mike Thomase68703c2010-11-07 19:58:55 +00001967 v4l2_std_id std_id;
1968 struct easycap_standard const *peasycap_standard;
R.M. Thomas702422b2010-06-18 12:29:49 -07001969
Mike Thomase68703c2010-11-07 19:58:55 +00001970 JOM(8, "VIDIOC_G_STD\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07001971
Mike Thomasf36bc372010-11-07 20:00:35 +00001972 if (0 > peasycap->standard_offset) {
1973 JOM(8, "%i=peasycap->standard_offset\n", \
1974 peasycap->standard_offset);
Mike Thomasae59dad2010-11-07 20:09:19 +00001975 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasf36bc372010-11-07 20:00:35 +00001976 return -EBUSY;
1977 }
1978
R.M. Thomas702422b2010-06-18 12:29:49 -07001979 if (0 != copy_from_user(&std_id, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001980 sizeof(v4l2_std_id))) {
1981 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001982 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001983 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001984
1985 peasycap_standard = &easycap_standard[peasycap->standard_offset];
1986 std_id = peasycap_standard->v4l2_standard.id;
1987
Mike Thomase68703c2010-11-07 19:58:55 +00001988 JOM(8, "user is told: %s\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07001989 &peasycap_standard->v4l2_standard.name[0]);
1990
1991 if (0 != copy_to_user((void __user *)arg, &std_id, \
Mike Thomasae59dad2010-11-07 20:09:19 +00001992 sizeof(v4l2_std_id))) {
1993 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07001994 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00001995 }
R.M. Thomas702422b2010-06-18 12:29:49 -07001996 break;
1997}
1998/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1999case VIDIOC_S_STD: {
Mike Thomase68703c2010-11-07 19:58:55 +00002000 v4l2_std_id std_id;
2001 int rc;
R.M. Thomas702422b2010-06-18 12:29:49 -07002002
Mike Thomase68703c2010-11-07 19:58:55 +00002003 JOM(8, "VIDIOC_S_STD\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002004
2005 if (0 != copy_from_user(&std_id, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002006 sizeof(v4l2_std_id))) {
2007 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002008 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002009 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002010
Mike Thomas40b8d502010-11-07 20:02:15 +00002011 JOM(8, "User requests standard: 0x%08X%08X\n", \
2012 (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32), \
2013 (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
2014
R.M. Thomas702422b2010-06-18 12:29:49 -07002015 rc = adjust_standard(peasycap, std_id);
2016 if (0 > rc) {
Mike Thomase68703c2010-11-07 19:58:55 +00002017 JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
Mike Thomasae59dad2010-11-07 20:09:19 +00002018 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002019 return -ENOENT;
2020 }
2021 break;
2022}
2023/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2024case VIDIOC_REQBUFS: {
Mike Thomase68703c2010-11-07 19:58:55 +00002025 int nbuffers;
2026 struct v4l2_requestbuffers v4l2_requestbuffers;
R.M. Thomas702422b2010-06-18 12:29:49 -07002027
Mike Thomase68703c2010-11-07 19:58:55 +00002028 JOM(8, "VIDIOC_REQBUFS\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002029
2030 if (0 != copy_from_user(&v4l2_requestbuffers, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002031 sizeof(struct v4l2_requestbuffers))) {
2032 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002033 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002034 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002035
Mike Thomasae59dad2010-11-07 20:09:19 +00002036 if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2037 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002038 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002039 }
2040 if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
2041 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002042 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002043 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002044 nbuffers = v4l2_requestbuffers.count;
Mike Thomase68703c2010-11-07 19:58:55 +00002045 JOM(8, " User requests %i buffers ...\n", nbuffers);
R.M. Thomas702422b2010-06-18 12:29:49 -07002046 if (nbuffers < 2)
2047 nbuffers = 2;
2048 if (nbuffers > FRAME_BUFFER_MANY)
2049 nbuffers = FRAME_BUFFER_MANY;
2050 if (v4l2_requestbuffers.count == nbuffers) {
Mike Thomase68703c2010-11-07 19:58:55 +00002051 JOM(8, " ... agree to %i buffers\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002052 nbuffers);
2053 } else {
Mike Thomase68703c2010-11-07 19:58:55 +00002054 JOM(8, " ... insist on %i buffers\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002055 nbuffers);
2056 v4l2_requestbuffers.count = nbuffers;
2057 }
2058 peasycap->frame_buffer_many = nbuffers;
2059
2060 if (0 != copy_to_user((void __user *)arg, &v4l2_requestbuffers, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002061 sizeof(struct v4l2_requestbuffers))) {
2062 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002063 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002064 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002065 break;
2066}
2067/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2068case VIDIOC_QUERYBUF: {
Mike Thomase68703c2010-11-07 19:58:55 +00002069 __u32 index;
2070 struct v4l2_buffer v4l2_buffer;
R.M. Thomas702422b2010-06-18 12:29:49 -07002071
Mike Thomase68703c2010-11-07 19:58:55 +00002072 JOM(8, "VIDIOC_QUERYBUF\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002073
2074 if (peasycap->video_eof) {
Mike Thomasf36bc372010-11-07 20:00:35 +00002075 JOM(8, "returning -EIO because %i=video_eof\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002076 peasycap->video_eof);
Mike Thomasae59dad2010-11-07 20:09:19 +00002077 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasf36bc372010-11-07 20:00:35 +00002078 return -EIO;
R.M. Thomas702422b2010-06-18 12:29:49 -07002079 }
2080
2081 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002082 sizeof(struct v4l2_buffer))) {
2083 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002084 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002085 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002086
Mike Thomasae59dad2010-11-07 20:09:19 +00002087 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2088 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002089 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002090 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002091 index = v4l2_buffer.index;
2092 if (index < 0 || index >= peasycap->frame_buffer_many)
2093 return -EINVAL;
2094 memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
2095 v4l2_buffer.index = index;
2096 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2097 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2098 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | \
2099 peasycap->done[index] | \
2100 peasycap->queued[index];
Mike Thomas40b8d502010-11-07 20:02:15 +00002101 v4l2_buffer.field = V4L2_FIELD_NONE;
R.M. Thomas702422b2010-06-18 12:29:49 -07002102 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2103 v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
2104 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2105
Mike Thomase68703c2010-11-07 19:58:55 +00002106 JOM(16, " %10i=index\n", v4l2_buffer.index);
2107 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2108 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2109 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2110 JOM(16, " %10i=field\n", v4l2_buffer.field);
2111 JOM(16, " %10li=timestamp.tv_usec\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002112 (long)v4l2_buffer.timestamp.tv_usec);
Mike Thomase68703c2010-11-07 19:58:55 +00002113 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2114 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2115 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2116 JOM(16, " %10i=length\n", v4l2_buffer.length);
R.M. Thomas702422b2010-06-18 12:29:49 -07002117
2118 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002119 sizeof(struct v4l2_buffer))) {
2120 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002121 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002122 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002123 break;
2124}
2125/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2126case VIDIOC_QBUF: {
Mike Thomase68703c2010-11-07 19:58:55 +00002127 struct v4l2_buffer v4l2_buffer;
R.M. Thomas702422b2010-06-18 12:29:49 -07002128
Mike Thomase68703c2010-11-07 19:58:55 +00002129 JOM(8, "VIDIOC_QBUF\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002130
2131 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002132 sizeof(struct v4l2_buffer))) {
2133 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002134 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002135 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002136
Mike Thomasae59dad2010-11-07 20:09:19 +00002137 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2138 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002139 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002140 }
2141 if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
2142 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002143 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002144 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002145 if (v4l2_buffer.index < 0 || \
Mike Thomasae59dad2010-11-07 20:09:19 +00002146 (v4l2_buffer.index >= peasycap->frame_buffer_many)) {
2147 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002148 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002149 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002150 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
2151
2152 peasycap->done[v4l2_buffer.index] = 0;
2153 peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
2154
2155 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002156 sizeof(struct v4l2_buffer))) {
2157 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002158 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002159 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002160
Mike Thomase68703c2010-11-07 19:58:55 +00002161 JOM(8, "..... user queueing frame buffer %i\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002162 (int)v4l2_buffer.index);
2163
2164 peasycap->frame_lock = 0;
2165
2166 break;
2167}
2168/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2169case VIDIOC_DQBUF:
2170 {
2171#if defined(AUDIOTIME)
Mike Thomase68703c2010-11-07 19:58:55 +00002172 struct signed_div_result sdr;
2173 long long int above, below, dnbydt, fudge, sll;
2174 unsigned long long int ull;
Mike Thomasf36bc372010-11-07 20:00:35 +00002175 struct timeval timeval8;
R.M. Thomas702422b2010-06-18 12:29:49 -07002176 struct timeval timeval1;
2177#endif /*AUDIOTIME*/
Mike Thomase68703c2010-11-07 19:58:55 +00002178 struct timeval timeval, timeval2;
2179 int i, j;
2180 struct v4l2_buffer v4l2_buffer;
Mike Thomasf36bc372010-11-07 20:00:35 +00002181 int rcdq;
2182 __u16 input;
R.M. Thomas702422b2010-06-18 12:29:49 -07002183
Mike Thomase68703c2010-11-07 19:58:55 +00002184 JOM(8, "VIDIOC_DQBUF\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002185
2186 if ((peasycap->video_idle) || (peasycap->video_eof)) {
Mike Thomase68703c2010-11-07 19:58:55 +00002187 JOM(8, "returning -EIO because " \
R.M. Thomas702422b2010-06-18 12:29:49 -07002188 "%i=video_idle %i=video_eof\n", \
2189 peasycap->video_idle, peasycap->video_eof);
Mike Thomasae59dad2010-11-07 20:09:19 +00002190 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002191 return -EIO;
2192 }
2193
2194 if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002195 sizeof(struct v4l2_buffer))) {
2196 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002197 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002198 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002199
Mike Thomasae59dad2010-11-07 20:09:19 +00002200 if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2201 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002202 return -EINVAL;
Mike Thomasae59dad2010-11-07 20:09:19 +00002203 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002204
Mike Thomas40b8d502010-11-07 20:02:15 +00002205 if (true == peasycap->offerfields) {
2206 /*-----------------------------------------------------------*/
2207 /*
2208 * IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
2209 * V4L2_FIELD_BOTTOM
2210 */
2211 /*-----------------------------------------------------------*/
2212 if (V4L2_FIELD_TOP == v4l2_buffer.field)
2213 JOM(8, "user wants V4L2_FIELD_TOP\n");
2214 else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
2215 JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
2216 else if (V4L2_FIELD_ANY == v4l2_buffer.field)
2217 JOM(8, "user wants V4L2_FIELD_ANY\n");
2218 else
2219 JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n", \
2220 v4l2_buffer.field);
2221 }
2222
R.M. Thomas702422b2010-06-18 12:29:49 -07002223 if (!peasycap->video_isoc_streaming) {
Mike Thomase68703c2010-11-07 19:58:55 +00002224 JOM(16, "returning -EIO because video urbs not streaming\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002225 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002226 return -EIO;
2227 }
2228/*---------------------------------------------------------------------------*/
2229/*
2230 * IF THE USER HAS PREVIOUSLY CALLED easycap_poll(), AS DETERMINED BY FINDING
2231 * THE FLAG peasycap->polled SET, THERE MUST BE NO FURTHER WAIT HERE. IN THIS
2232 * CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
2233 */
2234/*---------------------------------------------------------------------------*/
2235
2236 if (!peasycap->polled) {
Mike Thomasf36bc372010-11-07 20:00:35 +00002237 do {
2238 rcdq = easycap_dqbuf(peasycap, 0);
2239 if (-EIO == rcdq) {
2240 JOM(8, "returning -EIO because " \
2241 "dqbuf() returned -EIO\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002242 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomasf36bc372010-11-07 20:00:35 +00002243 return -EIO;
2244 }
2245 } while (0 != rcdq);
R.M. Thomas702422b2010-06-18 12:29:49 -07002246 } else {
Mike Thomasae59dad2010-11-07 20:09:19 +00002247 if (peasycap->video_eof) {
2248 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002249 return -EIO;
Mike Thomasae59dad2010-11-07 20:09:19 +00002250 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002251 }
2252 if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
Mike Thomase68703c2010-11-07 19:58:55 +00002253 SAM("ERROR: V4L2_BUF_FLAG_DONE != 0x%08X\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002254 peasycap->done[peasycap->frame_read]);
2255 }
2256 peasycap->polled = 0;
2257
Mike Thomase68703c2010-11-07 19:58:55 +00002258 if (!(peasycap->isequence % 10)) {
R.M. Thomas702422b2010-06-18 12:29:49 -07002259 for (i = 0; i < 179; i++)
2260 peasycap->merit[i] = peasycap->merit[i+1];
2261 peasycap->merit[179] = merit_saa(peasycap->pusb_device);
2262 j = 0;
2263 for (i = 0; i < 180; i++)
2264 j += peasycap->merit[i];
2265 if (90 < j) {
Mike Thomase68703c2010-11-07 19:58:55 +00002266 SAM("easycap driver shutting down " \
R.M. Thomas702422b2010-06-18 12:29:49 -07002267 "on condition blue\n");
2268 peasycap->video_eof = 1; peasycap->audio_eof = 1;
2269 }
2270 }
2271
2272 v4l2_buffer.index = peasycap->frame_read;
2273 v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
2274 v4l2_buffer.bytesused = peasycap->frame_buffer_used;
2275 v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
Mike Thomas40b8d502010-11-07 20:02:15 +00002276 if (true == peasycap->offerfields)
2277 v4l2_buffer.field = V4L2_FIELD_BOTTOM;
2278 else
2279 v4l2_buffer.field = V4L2_FIELD_NONE;
R.M. Thomas702422b2010-06-18 12:29:49 -07002280 do_gettimeofday(&timeval);
2281 timeval2 = timeval;
2282
2283#if defined(AUDIOTIME)
2284 if (!peasycap->timeval0.tv_sec) {
Mike Thomasf36bc372010-11-07 20:00:35 +00002285 timeval8 = timeval;
R.M. Thomas702422b2010-06-18 12:29:49 -07002286 timeval1 = timeval;
2287 timeval2 = timeval;
2288 dnbydt = 192000;
Mike Thomasf36bc372010-11-07 20:00:35 +00002289 peasycap->timeval0 = timeval8;
R.M. Thomas702422b2010-06-18 12:29:49 -07002290 } else {
R.M. Thomas702422b2010-06-18 12:29:49 -07002291 dnbydt = peasycap->dnbydt;
2292 timeval1 = peasycap->timeval1;
R.M. Thomas702422b2010-06-18 12:29:49 -07002293 above = dnbydt * MICROSECONDS(timeval, timeval1);
2294 below = 192000;
2295 sdr = signed_div(above, below);
2296
2297 above = sdr.quotient + timeval1.tv_usec - 350000;
2298
2299 below = 1000000;
2300 sdr = signed_div(above, below);
2301 timeval2.tv_usec = sdr.remainder;
2302 timeval2.tv_sec = timeval1.tv_sec + sdr.quotient;
2303 }
Mike Thomase68703c2010-11-07 19:58:55 +00002304 if (!(peasycap->isequence % 500)) {
R.M. Thomas702422b2010-06-18 12:29:49 -07002305 fudge = ((long long int)(1000000)) * \
2306 ((long long int)(timeval.tv_sec - \
2307 timeval2.tv_sec)) + \
2308 (long long int)(timeval.tv_usec - \
Mike Thomas268dfed2010-11-07 20:11:36 +00002309 timeval2.tv_usec);
R.M. Thomas702422b2010-06-18 12:29:49 -07002310 sdr = signed_div(fudge, 1000);
2311 sll = sdr.quotient;
2312 ull = sdr.remainder;
2313
Mike Thomase68703c2010-11-07 19:58:55 +00002314 SAM("%5lli.%-3lli=ms timestamp fudge\n", sll, ull);
R.M. Thomas702422b2010-06-18 12:29:49 -07002315 }
2316#endif /*AUDIOTIME*/
2317
2318 v4l2_buffer.timestamp = timeval2;
Mike Thomase68703c2010-11-07 19:58:55 +00002319 v4l2_buffer.sequence = peasycap->isequence++;
R.M. Thomas702422b2010-06-18 12:29:49 -07002320 v4l2_buffer.memory = V4L2_MEMORY_MMAP;
2321 v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
2322 v4l2_buffer.length = FRAME_BUFFER_SIZE;
2323
Mike Thomase68703c2010-11-07 19:58:55 +00002324 JOM(16, " %10i=index\n", v4l2_buffer.index);
2325 JOM(16, " 0x%08X=type\n", v4l2_buffer.type);
2326 JOM(16, " %10i=bytesused\n", v4l2_buffer.bytesused);
2327 JOM(16, " 0x%08X=flags\n", v4l2_buffer.flags);
2328 JOM(16, " %10i=field\n", v4l2_buffer.field);
Mike Thomas268dfed2010-11-07 20:11:36 +00002329 JOM(16, " %10li=timestamp.tv_sec\n", \
2330 (long)v4l2_buffer.timestamp.tv_sec);
Mike Thomase68703c2010-11-07 19:58:55 +00002331 JOM(16, " %10li=timestamp.tv_usec\n", \
R.M. Thomas702422b2010-06-18 12:29:49 -07002332 (long)v4l2_buffer.timestamp.tv_usec);
Mike Thomase68703c2010-11-07 19:58:55 +00002333 JOM(16, " %10i=sequence\n", v4l2_buffer.sequence);
2334 JOM(16, " 0x%08X=memory\n", v4l2_buffer.memory);
2335 JOM(16, " %10i=m.offset\n", v4l2_buffer.m.offset);
2336 JOM(16, " %10i=length\n", v4l2_buffer.length);
R.M. Thomas702422b2010-06-18 12:29:49 -07002337
2338 if (0 != copy_to_user((void __user *)arg, &v4l2_buffer, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002339 sizeof(struct v4l2_buffer))) {
2340 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002341 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002342 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002343
Mike Thomasf36bc372010-11-07 20:00:35 +00002344 input = peasycap->frame_buffer[peasycap->frame_read][0].input;
2345 if (0x08 & input) {
2346 JOM(8, "user is offered frame buffer %i, input %i\n", \
2347 peasycap->frame_read, (0x07 & input));
2348 } else {
2349 JOM(8, "user is offered frame buffer %i\n", \
2350 peasycap->frame_read);
2351 }
2352 peasycap->frame_lock = 1;
2353 JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
R.M. Thomas702422b2010-06-18 12:29:49 -07002354 if (peasycap->frame_read == peasycap->frame_fill) {
2355 if (peasycap->frame_lock) {
Mike Thomasf36bc372010-11-07 20:00:35 +00002356 JOM(8, "WORRY: filling frame buffer " \
R.M. Thomas702422b2010-06-18 12:29:49 -07002357 "while offered to user\n");
2358 }
2359 }
2360 break;
2361}
2362/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
R.M. Thomas702422b2010-06-18 12:29:49 -07002363case VIDIOC_STREAMON: {
Mike Thomase68703c2010-11-07 19:58:55 +00002364 int i;
R.M. Thomas702422b2010-06-18 12:29:49 -07002365
Mike Thomase68703c2010-11-07 19:58:55 +00002366 JOM(8, "VIDIOC_STREAMON\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002367
Mike Thomase68703c2010-11-07 19:58:55 +00002368 peasycap->isequence = 0;
R.M. Thomas702422b2010-06-18 12:29:49 -07002369 for (i = 0; i < 180; i++)
2370 peasycap->merit[i] = 0;
2371 if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +00002372 SAM("ERROR: peasycap->pusb_device is NULL\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002373 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002374 return -EFAULT;
2375 }
2376 submit_video_urbs(peasycap);
2377 peasycap->video_idle = 0;
2378 peasycap->audio_idle = 0;
2379 peasycap->video_eof = 0;
2380 peasycap->audio_eof = 0;
2381 break;
2382}
2383/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2384case VIDIOC_STREAMOFF: {
Mike Thomase68703c2010-11-07 19:58:55 +00002385 JOM(8, "VIDIOC_STREAMOFF\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002386
2387 if ((struct usb_device *)NULL == peasycap->pusb_device) {
Mike Thomase68703c2010-11-07 19:58:55 +00002388 SAM("ERROR: peasycap->pusb_device is NULL\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002389 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002390 return -EFAULT;
2391 }
2392
2393 peasycap->video_idle = 1;
2394 peasycap->audio_idle = 1; peasycap->timeval0.tv_sec = 0;
2395/*---------------------------------------------------------------------------*/
2396/*
2397 * IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
2398 * THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT. BEWARE.
2399 */
2400/*---------------------------------------------------------------------------*/
Mike Thomase68703c2010-11-07 19:58:55 +00002401 JOM(8, "calling wake_up on wq_video and wq_audio\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002402 wake_up_interruptible(&(peasycap->wq_video));
2403 wake_up_interruptible(&(peasycap->wq_audio));
2404/*---------------------------------------------------------------------------*/
2405 break;
2406}
2407/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2408case VIDIOC_G_PARM: {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002409 struct v4l2_streamparm *pv4l2_streamparm;
R.M. Thomas702422b2010-06-18 12:29:49 -07002410
Mike Thomase68703c2010-11-07 19:58:55 +00002411 JOM(8, "VIDIOC_G_PARM\n");
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002412 pv4l2_streamparm = kzalloc(sizeof(struct v4l2_streamparm), GFP_KERNEL);
2413 if (!pv4l2_streamparm) {
2414 SAM("ERROR: out of memory\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002415 mutex_unlock(&easycap_dongle[kd].mutex_video);
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002416 return -ENOMEM;
2417 }
2418 if (0 != copy_from_user(pv4l2_streamparm, (void __user *)arg, \
2419 sizeof(struct v4l2_streamparm))) {
2420 kfree(pv4l2_streamparm);
Mike Thomasae59dad2010-11-07 20:09:19 +00002421 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002422 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002423 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002424
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002425 if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2426 kfree(pv4l2_streamparm);
Mike Thomasae59dad2010-11-07 20:09:19 +00002427 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002428 return -EINVAL;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002429 }
2430 pv4l2_streamparm->parm.capture.capability = 0;
2431 pv4l2_streamparm->parm.capture.capturemode = 0;
2432 pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
Mike Thomasf36bc372010-11-07 20:00:35 +00002433
2434 if (peasycap->fps) {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002435 pv4l2_streamparm->parm.capture.timeperframe.\
Mike Thomasf36bc372010-11-07 20:00:35 +00002436 denominator = peasycap->fps;
2437 } else {
2438 if (true == peasycap->ntsc) {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002439 pv4l2_streamparm->parm.capture.timeperframe.\
Mike Thomasf36bc372010-11-07 20:00:35 +00002440 denominator = 30;
2441 } else {
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002442 pv4l2_streamparm->parm.capture.timeperframe.\
Mike Thomasf36bc372010-11-07 20:00:35 +00002443 denominator = 25;
2444 }
2445 }
2446
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002447 pv4l2_streamparm->parm.capture.readbuffers = \
2448 peasycap->frame_buffer_many;
2449 pv4l2_streamparm->parm.capture.extendedmode = 0;
2450 if (0 != copy_to_user((void __user *)arg, pv4l2_streamparm, \
2451 sizeof(struct v4l2_streamparm))) {
2452 kfree(pv4l2_streamparm);
Mike Thomasae59dad2010-11-07 20:09:19 +00002453 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002454 return -EFAULT;
Mike Thomas2a87a0b2010-11-07 20:07:12 +00002455 }
2456 kfree(pv4l2_streamparm);
R.M. Thomas702422b2010-06-18 12:29:49 -07002457 break;
2458}
2459/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2460case VIDIOC_S_PARM: {
Mike Thomase68703c2010-11-07 19:58:55 +00002461 JOM(8, "VIDIOC_S_PARM unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002462 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002463 return -EINVAL;
2464}
2465/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2466case VIDIOC_G_AUDIO: {
Mike Thomase68703c2010-11-07 19:58:55 +00002467 JOM(8, "VIDIOC_G_AUDIO unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002468 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002469 return -EINVAL;
2470}
2471/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2472case VIDIOC_S_AUDIO: {
Mike Thomase68703c2010-11-07 19:58:55 +00002473 JOM(8, "VIDIOC_S_AUDIO unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002474 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002475 return -EINVAL;
2476}
2477/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2478case VIDIOC_S_TUNER: {
Mike Thomase68703c2010-11-07 19:58:55 +00002479 JOM(8, "VIDIOC_S_TUNER unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002480 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002481 return -EINVAL;
2482}
2483/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2484case VIDIOC_G_FBUF:
2485case VIDIOC_S_FBUF:
2486case VIDIOC_OVERLAY: {
Mike Thomase68703c2010-11-07 19:58:55 +00002487 JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002488 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002489 return -EINVAL;
2490}
2491/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2492case VIDIOC_G_TUNER: {
Mike Thomase68703c2010-11-07 19:58:55 +00002493 JOM(8, "VIDIOC_G_TUNER unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002494 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002495 return -EINVAL;
2496}
2497case VIDIOC_G_FREQUENCY:
2498case VIDIOC_S_FREQUENCY: {
Mike Thomase68703c2010-11-07 19:58:55 +00002499 JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002500 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002501 return -EINVAL;
2502}
2503/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2504default: {
Mike Thomase68703c2010-11-07 19:58:55 +00002505 JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
Mike Thomasae59dad2010-11-07 20:09:19 +00002506 mutex_unlock(&easycap_dongle[kd].mutex_video);
R.M. Thomas702422b2010-06-18 12:29:49 -07002507 return -ENOIOCTLCMD;
2508}
2509}
Mike Thomasae59dad2010-11-07 20:09:19 +00002510mutex_unlock(&easycap_dongle[kd].mutex_video);
2511JOM(4, "unlocked easycap_dongle[%i].mutex_video\n", kd);
R.M. Thomas702422b2010-06-18 12:29:49 -07002512return 0;
2513}
Mike Thomase68703c2010-11-07 19:58:55 +00002514/*****************************************************************************/
Mike Thomasae59dad2010-11-07 20:09:19 +00002515/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
2516#if ((defined(EASYCAP_IS_VIDEODEV_CLIENT)) || \
2517 (defined(EASYCAP_NEEDS_UNLOCKED_IOCTL)))
2518long
2519easysnd_ioctl_noinode(struct file *file, unsigned int cmd, unsigned long arg) {
2520 return (long)easysnd_ioctl((struct inode *)NULL, file, cmd, arg);
2521}
2522#endif /*EASYCAP_IS_VIDEODEV_CLIENT||EASYCAP_NEEDS_UNLOCKED_IOCTL*/
2523/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
2524/*---------------------------------------------------------------------------*/
2525int
2526easysnd_ioctl(struct inode *inode, struct file *file,
2527 unsigned int cmd, unsigned long arg)
R.M. Thomas702422b2010-06-18 12:29:49 -07002528{
2529struct easycap *peasycap;
2530struct usb_device *p;
Mike Thomasae59dad2010-11-07 20:09:19 +00002531int kd;
R.M. Thomas702422b2010-06-18 12:29:49 -07002532
Mike Thomase68703c2010-11-07 19:58:55 +00002533if (NULL == file) {
2534 SAY("ERROR: file is NULL\n");
2535 return -ERESTARTSYS;
2536}
Joe Perchesba952d82010-07-12 13:50:10 -07002537peasycap = file->private_data;
R.M. Thomas702422b2010-06-18 12:29:49 -07002538if (NULL == peasycap) {
2539 SAY("ERROR: peasycap is NULL.\n");
Mike Thomase68703c2010-11-07 19:58:55 +00002540 return -EFAULT;
R.M. Thomas702422b2010-06-18 12:29:49 -07002541}
Mike Thomas268dfed2010-11-07 20:11:36 +00002542if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2543 SAY("ERROR: bad peasycap\n");
2544 return -EFAULT;
2545}
R.M. Thomas702422b2010-06-18 12:29:49 -07002546p = peasycap->pusb_device;
Mike Thomase68703c2010-11-07 19:58:55 +00002547if (NULL == p) {
2548 SAM("ERROR: peasycap->pusb_device is NULL\n");
2549 return -EFAULT;
2550}
Mike Thomasae59dad2010-11-07 20:09:19 +00002551kd = isdongle(peasycap);
2552if (0 <= kd && DONGLE_MANY > kd) {
2553 if (mutex_lock_interruptible(&easycap_dongle[kd].mutex_audio)) {
2554 SAY("ERROR: cannot lock easycap_dongle[%i].mutex_audio\n", kd);
2555 return -ERESTARTSYS;
2556 }
2557 JOM(4, "locked easycap_dongle[%i].mutex_audio\n", kd);
2558/*---------------------------------------------------------------------------*/
2559/*
2560 * MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
2561 * IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
2562 * IF NECESSARY, BAIL OUT.
2563*/
2564/*---------------------------------------------------------------------------*/
2565 if (kd != isdongle(peasycap))
2566 return -ERESTARTSYS;
2567 if (NULL == file) {
2568 SAY("ERROR: file is NULL\n");
2569 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2570 return -ERESTARTSYS;
2571 }
2572 peasycap = file->private_data;
2573 if (NULL == peasycap) {
2574 SAY("ERROR: peasycap is NULL\n");
2575 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2576 return -ERESTARTSYS;
2577 }
Mike Thomas268dfed2010-11-07 20:11:36 +00002578 if (memcmp(&peasycap->telltale[0], TELLTALE, strlen(TELLTALE))) {
2579 SAY("ERROR: bad peasycap\n");
2580 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2581 return -EFAULT;
2582 }
Mike Thomasae59dad2010-11-07 20:09:19 +00002583 p = peasycap->pusb_device;
2584 if (NULL == peasycap->pusb_device) {
2585 SAM("ERROR: peasycap->pusb_device is NULL\n");
2586 mutex_unlock(&easycap_dongle[kd].mutex_audio);
2587 return -ERESTARTSYS;
2588 }
2589} else {
2590/*---------------------------------------------------------------------------*/
2591/*
2592 * IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
2593 * ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED. BAIL OUT.
2594*/
2595/*---------------------------------------------------------------------------*/
2596 return -ERESTARTSYS;
2597}
R.M. Thomas702422b2010-06-18 12:29:49 -07002598/*---------------------------------------------------------------------------*/
2599switch (cmd) {
2600case SNDCTL_DSP_GETCAPS: {
2601 int caps;
Mike Thomase68703c2010-11-07 19:58:55 +00002602 JOM(8, "SNDCTL_DSP_GETCAPS\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002603
Mike Thomas7ebc8762010-07-11 10:54:51 +01002604#if defined(UPSAMPLE)
2605 if (true == peasycap->microphone)
2606 caps = 0x04400000;
2607 else
2608 caps = 0x04400000;
2609#else
R.M. Thomas702422b2010-06-18 12:29:49 -07002610 if (true == peasycap->microphone)
2611 caps = 0x02400000;
2612 else
2613 caps = 0x04400000;
Mike Thomas7ebc8762010-07-11 10:54:51 +01002614#endif /*UPSAMPLE*/
R.M. Thomas702422b2010-06-18 12:29:49 -07002615
Mike Thomasae59dad2010-11-07 20:09:19 +00002616 if (0 != copy_to_user((void __user *)arg, &caps, sizeof(int))) {
2617 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002618 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002619 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002620 break;
2621}
2622case SNDCTL_DSP_GETFMTS: {
2623 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002624 JOM(8, "SNDCTL_DSP_GETFMTS\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002625
Mike Thomas7ebc8762010-07-11 10:54:51 +01002626#if defined(UPSAMPLE)
R.M. Thomas702422b2010-06-18 12:29:49 -07002627 if (true == peasycap->microphone)
2628 incoming = AFMT_S16_LE;
2629 else
2630 incoming = AFMT_S16_LE;
Mike Thomas7ebc8762010-07-11 10:54:51 +01002631#else
2632 if (true == peasycap->microphone)
2633 incoming = AFMT_S16_LE;
2634 else
2635 incoming = AFMT_S16_LE;
2636#endif /*UPSAMPLE*/
R.M. Thomas702422b2010-06-18 12:29:49 -07002637
Mike Thomasae59dad2010-11-07 20:09:19 +00002638 if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2639 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002640 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002641 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002642 break;
2643}
2644case SNDCTL_DSP_SETFMT: {
2645 int incoming, outgoing;
Mike Thomase68703c2010-11-07 19:58:55 +00002646 JOM(8, "SNDCTL_DSP_SETFMT\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002647 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2648 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002649 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002650 }
Mike Thomase68703c2010-11-07 19:58:55 +00002651 JOM(8, "........... %i=incoming\n", incoming);
R.M. Thomas702422b2010-06-18 12:29:49 -07002652
Mike Thomas7ebc8762010-07-11 10:54:51 +01002653#if defined(UPSAMPLE)
R.M. Thomas702422b2010-06-18 12:29:49 -07002654 if (true == peasycap->microphone)
2655 outgoing = AFMT_S16_LE;
2656 else
2657 outgoing = AFMT_S16_LE;
Mike Thomas7ebc8762010-07-11 10:54:51 +01002658#else
2659 if (true == peasycap->microphone)
2660 outgoing = AFMT_S16_LE;
2661 else
2662 outgoing = AFMT_S16_LE;
2663#endif /*UPSAMPLE*/
R.M. Thomas702422b2010-06-18 12:29:49 -07002664
2665 if (incoming != outgoing) {
Mike Thomase68703c2010-11-07 19:58:55 +00002666 JOM(8, "........... %i=outgoing\n", outgoing);
2667 JOM(8, " cf. %i=AFMT_S16_LE\n", AFMT_S16_LE);
2668 JOM(8, " cf. %i=AFMT_U8\n", AFMT_U8);
R.M. Thomas702422b2010-06-18 12:29:49 -07002669 if (0 != copy_to_user((void __user *)arg, &outgoing, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002670 sizeof(int))) {
2671 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002672 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002673 }
2674 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002675 return -EINVAL ;
2676 }
2677 break;
2678}
2679case SNDCTL_DSP_STEREO: {
2680 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002681 JOM(8, "SNDCTL_DSP_STEREO\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002682 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2683 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002684 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002685 }
Mike Thomase68703c2010-11-07 19:58:55 +00002686 JOM(8, "........... %i=incoming\n", incoming);
R.M. Thomas702422b2010-06-18 12:29:49 -07002687
Mike Thomas7ebc8762010-07-11 10:54:51 +01002688#if defined(UPSAMPLE)
2689 if (true == peasycap->microphone)
2690 incoming = 1;
2691 else
2692 incoming = 1;
2693#else
R.M. Thomas702422b2010-06-18 12:29:49 -07002694 if (true == peasycap->microphone)
2695 incoming = 0;
2696 else
2697 incoming = 1;
Mike Thomas7ebc8762010-07-11 10:54:51 +01002698#endif /*UPSAMPLE*/
R.M. Thomas702422b2010-06-18 12:29:49 -07002699
Mike Thomasae59dad2010-11-07 20:09:19 +00002700 if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2701 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002702 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002703 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002704 break;
2705}
2706case SNDCTL_DSP_SPEED: {
2707 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002708 JOM(8, "SNDCTL_DSP_SPEED\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002709 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2710 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002711 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002712 }
Mike Thomase68703c2010-11-07 19:58:55 +00002713 JOM(8, "........... %i=incoming\n", incoming);
R.M. Thomas702422b2010-06-18 12:29:49 -07002714
Mike Thomas7ebc8762010-07-11 10:54:51 +01002715#if defined(UPSAMPLE)
2716 if (true == peasycap->microphone)
2717 incoming = 32000;
2718 else
2719 incoming = 48000;
2720#else
R.M. Thomas702422b2010-06-18 12:29:49 -07002721 if (true == peasycap->microphone)
2722 incoming = 8000;
2723 else
2724 incoming = 48000;
Mike Thomas7ebc8762010-07-11 10:54:51 +01002725#endif /*UPSAMPLE*/
R.M. Thomas702422b2010-06-18 12:29:49 -07002726
Mike Thomasae59dad2010-11-07 20:09:19 +00002727 if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2728 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002729 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002730 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002731 break;
2732}
2733case SNDCTL_DSP_GETTRIGGER: {
2734 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002735 JOM(8, "SNDCTL_DSP_GETTRIGGER\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002736 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2737 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002738 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002739 }
Mike Thomase68703c2010-11-07 19:58:55 +00002740 JOM(8, "........... %i=incoming\n", incoming);
R.M. Thomas702422b2010-06-18 12:29:49 -07002741
2742 incoming = PCM_ENABLE_INPUT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002743 if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2744 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002745 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002746 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002747 break;
2748}
2749case SNDCTL_DSP_SETTRIGGER: {
2750 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002751 JOM(8, "SNDCTL_DSP_SETTRIGGER\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002752 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2753 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002754 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002755 }
Mike Thomase68703c2010-11-07 19:58:55 +00002756 JOM(8, "........... %i=incoming\n", incoming);
2757 JOM(8, "........... cf 0x%x=PCM_ENABLE_INPUT " \
R.M. Thomas702422b2010-06-18 12:29:49 -07002758 "0x%x=PCM_ENABLE_OUTPUT\n", \
2759 PCM_ENABLE_INPUT, PCM_ENABLE_OUTPUT);
2760 ;
2761 ;
2762 ;
2763 ;
2764 break;
2765}
2766case SNDCTL_DSP_GETBLKSIZE: {
2767 int incoming;
Mike Thomase68703c2010-11-07 19:58:55 +00002768 JOM(8, "SNDCTL_DSP_GETBLKSIZE\n");
Mike Thomasae59dad2010-11-07 20:09:19 +00002769 if (0 != copy_from_user(&incoming, (void __user *)arg, sizeof(int))) {
2770 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002771 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002772 }
Mike Thomase68703c2010-11-07 19:58:55 +00002773 JOM(8, "........... %i=incoming\n", incoming);
Mike Thomas3d423e92010-07-11 10:51:13 +01002774 incoming = peasycap->audio_bytes_per_fragment;
Mike Thomasae59dad2010-11-07 20:09:19 +00002775 if (0 != copy_to_user((void __user *)arg, &incoming, sizeof(int))) {
2776 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002777 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002778 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002779 break;
2780}
2781case SNDCTL_DSP_GETISPACE: {
2782 struct audio_buf_info audio_buf_info;
2783
Mike Thomase68703c2010-11-07 19:58:55 +00002784 JOM(8, "SNDCTL_DSP_GETISPACE\n");
R.M. Thomas702422b2010-06-18 12:29:49 -07002785
Mike Thomas3d423e92010-07-11 10:51:13 +01002786 audio_buf_info.bytes = peasycap->audio_bytes_per_fragment;
R.M. Thomas702422b2010-06-18 12:29:49 -07002787 audio_buf_info.fragments = 1;
2788 audio_buf_info.fragsize = 0;
2789 audio_buf_info.fragstotal = 0;
2790
2791 if (0 != copy_to_user((void __user *)arg, &audio_buf_info, \
Mike Thomasae59dad2010-11-07 20:09:19 +00002792 sizeof(int))) {
2793 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002794 return -EFAULT;
Mike Thomasae59dad2010-11-07 20:09:19 +00002795 }
R.M. Thomas702422b2010-06-18 12:29:49 -07002796 break;
2797}
Mike Thomasf36bc372010-11-07 20:00:35 +00002798case 0x00005401:
2799case 0x00005402:
2800case 0x00005403:
2801case 0x00005404:
2802case 0x00005405:
2803case 0x00005406: {
2804 JOM(8, "SNDCTL_TMR_...: 0x%08X unsupported\n", cmd);
Mike Thomasae59dad2010-11-07 20:09:19 +00002805 mutex_unlock(&easycap_dongle[kd].mutex_audio);
Mike Thomasf36bc372010-11-07 20:00:35 +00002806 return -ENOIOCTLCMD;
2807}
R.M. Thomas702422b2010-06-18 12:29:49 -07002808default: {
Mike Thomase68703c2010-11-07 19:58:55 +00002809 JOM(8, "ERROR: unrecognized DSP IOCTL command: 0x%08X\n", cmd);
Mike Thomasae59dad2010-11-07 20:09:19 +00002810 mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002811 return -ENOIOCTLCMD;
2812}
2813}
Mike Thomasae59dad2010-11-07 20:09:19 +00002814mutex_unlock(&easycap_dongle[kd].mutex_audio);
R.M. Thomas702422b2010-06-18 12:29:49 -07002815return 0;
2816}
R.M. Thomas702422b2010-06-18 12:29:49 -07002817/*****************************************************************************/
Mike Thomas268dfed2010-11-07 20:11:36 +00002818
2819