blob: 6811bb91ee276a2e94956cdede5800a1f39410bd [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
Mike Iselyd8554972006-06-26 20:58:46 -03003 *
4 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
5 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090023#include <linux/slab.h>
Mauro Carvalho Chehabce4260c2006-06-26 22:26:08 -030024#include <linux/version.h>
Mike Iselyd8554972006-06-26 20:58:46 -030025#include "pvrusb2-context.h"
26#include "pvrusb2-hdw.h"
27#include "pvrusb2.h"
28#include "pvrusb2-debug.h"
29#include "pvrusb2-v4l2.h"
30#include "pvrusb2-ioread.h"
31#include <linux/videodev2.h>
Paul Gortmaker7a707b82011-07-03 14:03:12 -040032#include <linux/module.h>
Mike Isely43e06022006-09-23 23:47:50 -030033#include <media/v4l2-dev.h>
Mike Iselyd8554972006-06-26 20:58:46 -030034#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030035#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030036
37struct pvr2_v4l2_dev;
38struct pvr2_v4l2_fh;
39struct pvr2_v4l2;
40
Mike Iselyd8554972006-06-26 20:58:46 -030041struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030042 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030043 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030044 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030045 /* Information about this device: */
46 enum pvr2_config config; /* Expected stream format */
47 int v4l_type; /* V4L defined type for this device node */
48 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030049};
50
51struct pvr2_v4l2_fh {
52 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030053 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030054 enum v4l2_priority prio;
55 struct pvr2_ioread *rhp;
56 struct file *file;
57 struct pvr2_v4l2 *vhead;
58 struct pvr2_v4l2_fh *vnext;
59 struct pvr2_v4l2_fh *vprev;
60 wait_queue_head_t wait_data;
61 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030062 /* Map contiguous ordinal value to input id */
63 unsigned char *input_map;
64 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030065};
66
67struct pvr2_v4l2 {
68 struct pvr2_channel channel;
69 struct pvr2_v4l2_fh *vfirst;
70 struct pvr2_v4l2_fh *vlast;
71
72 struct v4l2_prio_state prio;
73
Mike Isely0f0f257b2006-12-27 23:19:42 -030074 /* streams - Note that these must be separately, individually,
75 * allocated pointers. This is because the v4l core is going to
76 * manage their deletion - separately, individually... */
77 struct pvr2_v4l2_dev *dev_video;
78 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030079};
80
81static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
82module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030083MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
84static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
85module_param_array(radio_nr, int, NULL, 0444);
86MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
87static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
88module_param_array(vbi_nr, int, NULL, 0444);
89MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030090
Adrian Bunk07e337e2006-06-30 11:30:20 -030091static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030092 .driver = "pvrusb2",
93 .card = "Hauppauge WinTV pvr-usb2",
94 .bus_info = "usb",
Mauro Carvalho Chehab083774d2011-06-25 13:34:24 -030095 .version = LINUX_VERSION_CODE,
Mike Iselyd166b022009-01-14 04:21:29 -030096 .capabilities = (V4L2_CAP_VIDEO_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030097 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030098 V4L2_CAP_READWRITE),
99 .reserved = {0,0,0,0}
100};
101
Adrian Bunk07e337e2006-06-30 11:30:20 -0300102static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300103 {
104 .index = 0,
105 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
106 .flags = V4L2_FMT_FLAG_COMPRESSED,
107 .description = "MPEG1/2",
108 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
109 // breaks when I do that.
110 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
111 .reserved = { 0, 0, 0, 0 }
112 }
113};
114
115#define PVR_FORMAT_PIX 0
116#define PVR_FORMAT_VBI 1
117
Adrian Bunk07e337e2006-06-30 11:30:20 -0300118static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300119 [PVR_FORMAT_PIX] = {
120 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
121 .fmt = {
122 .pix = {
123 .width = 720,
124 .height = 576,
125 // This should really be V4L2_PIX_FMT_MPEG,
126 // but xawtv breaks when I do that.
127 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
128 .field = V4L2_FIELD_INTERLACED,
129 .bytesperline = 0, // doesn't make sense
130 // here
131 //FIXME : Don't know what to put here...
132 .sizeimage = (32*1024),
133 .colorspace = 0, // doesn't make sense here
134 .priv = 0
135 }
136 }
137 },
138 [PVR_FORMAT_VBI] = {
139 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
140 .fmt = {
141 .vbi = {
142 .sampling_rate = 27000000,
143 .offset = 248,
144 .samples_per_line = 1443,
145 .sample_format = V4L2_PIX_FMT_GREY,
146 .start = { 0, 0 },
147 .count = { 0, 0 },
148 .flags = 0,
149 .reserved = { 0, 0 }
150 }
151 }
152 }
153};
154
Mike Isely16eb40d2006-12-30 18:27:32 -0300155
Mike Iselyd8554972006-06-26 20:58:46 -0300156/*
157 * pvr_ioctl()
158 *
159 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
160 *
161 */
Hans Verkuil069b7472008-12-30 07:04:34 -0300162static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300163{
164 struct pvr2_v4l2_fh *fh = file->private_data;
165 struct pvr2_v4l2 *vp = fh->vhead;
Joe Perches108bdd72010-04-05 16:05:39 -0300166 struct pvr2_v4l2_dev *pdi = fh->pdi;
Mike Iselyd8554972006-06-26 20:58:46 -0300167 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuil069b7472008-12-30 07:04:34 -0300168 long ret = -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300169
170 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
171 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
172 }
173
174 if (!pvr2_hdw_dev_ok(hdw)) {
175 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
176 "ioctl failed - bad or no context");
177 return -EFAULT;
178 }
179
180 /* check priority */
181 switch (cmd) {
182 case VIDIOC_S_CTRL:
183 case VIDIOC_S_STD:
184 case VIDIOC_S_INPUT:
185 case VIDIOC_S_TUNER:
186 case VIDIOC_S_FREQUENCY:
Hans Verkuilffb48772010-05-01 08:03:24 -0300187 ret = v4l2_prio_check(&vp->prio, fh->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300188 if (ret)
189 return ret;
190 }
191
192 switch (cmd) {
193 case VIDIOC_QUERYCAP:
194 {
195 struct v4l2_capability *cap = arg;
196
197 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300198 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
199 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300200 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300201
202 ret = 0;
203 break;
204 }
205
206 case VIDIOC_G_PRIORITY:
207 {
208 enum v4l2_priority *p = arg;
209
210 *p = v4l2_prio_max(&vp->prio);
211 ret = 0;
212 break;
213 }
214
215 case VIDIOC_S_PRIORITY:
216 {
217 enum v4l2_priority *prio = arg;
218
219 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
220 break;
221 }
222
223 case VIDIOC_ENUMSTD:
224 {
225 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
226 int idx = vs->index;
227 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
228 break;
229 }
230
231 case VIDIOC_G_STD:
232 {
233 int val = 0;
234 ret = pvr2_ctrl_get_value(
235 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
236 *(v4l2_std_id *)arg = val;
237 break;
238 }
239
240 case VIDIOC_S_STD:
241 {
242 ret = pvr2_ctrl_set_value(
243 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
244 *(v4l2_std_id *)arg);
245 break;
246 }
247
248 case VIDIOC_ENUMINPUT:
249 {
250 struct pvr2_ctrl *cptr;
251 struct v4l2_input *vi = (struct v4l2_input *)arg;
252 struct v4l2_input tmp;
253 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300254 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300255
256 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
257
258 memset(&tmp,0,sizeof(tmp));
259 tmp.index = vi->index;
260 ret = 0;
Roel Kluin223ffe52009-05-02 16:38:47 -0300261 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300262 ret = -EINVAL;
263 break;
264 }
Mike Iselye57b1c82008-04-21 03:52:34 -0300265 val = fh->input_map[vi->index];
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300266 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300267 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300268 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300269 case PVR2_CVAL_INPUT_RADIO:
270 tmp.type = V4L2_INPUT_TYPE_TUNER;
271 break;
272 case PVR2_CVAL_INPUT_SVIDEO:
273 case PVR2_CVAL_INPUT_COMPOSITE:
274 tmp.type = V4L2_INPUT_TYPE_CAMERA;
275 break;
276 default:
277 ret = -EINVAL;
278 break;
279 }
280 if (ret < 0) break;
281
282 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300283 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300284 tmp.name,sizeof(tmp.name)-1,&cnt);
285 tmp.name[cnt] = 0;
286
287 /* Don't bother with audioset, since this driver currently
288 always switches the audio whenever the video is
289 switched. */
290
291 /* Handling std is a tougher problem. It doesn't make
292 sense in cases where a device might be multi-standard.
293 We could just copy out the current value for the
294 standard, but it can change over time. For now just
295 leave it zero. */
296
297 memcpy(vi, &tmp, sizeof(tmp));
298
299 ret = 0;
300 break;
301 }
302
303 case VIDIOC_G_INPUT:
304 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300305 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300306 struct pvr2_ctrl *cptr;
307 struct v4l2_input *vi = (struct v4l2_input *)arg;
308 int val;
309 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
310 val = 0;
311 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300312 vi->index = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300313 for (idx = 0; idx < fh->input_cnt; idx++) {
314 if (fh->input_map[idx] == val) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300315 vi->index = idx;
316 break;
317 }
318 }
Mike Iselyd8554972006-06-26 20:58:46 -0300319 break;
320 }
321
322 case VIDIOC_S_INPUT:
323 {
324 struct v4l2_input *vi = (struct v4l2_input *)arg;
Roel Kluin223ffe52009-05-02 16:38:47 -0300325 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300326 ret = -ERANGE;
327 break;
328 }
Mike Iselyd8554972006-06-26 20:58:46 -0300329 ret = pvr2_ctrl_set_value(
330 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselye57b1c82008-04-21 03:52:34 -0300331 fh->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300332 break;
333 }
334
335 case VIDIOC_ENUMAUDIO:
336 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300337 /* pkt: FIXME: We are returning one "fake" input here
338 which could very well be called "whatever_we_like".
339 This is for apps that want to see an audio input
340 just to feel comfortable, as well as to test if
341 it can do stereo or sth. There is actually no guarantee
342 that the actual audio input cannot change behind the app's
343 back, but most applications should not mind that either.
344
345 Hopefully, mplayer people will work with us on this (this
346 whole mess is to support mplayer pvr://), or Hans will come
347 up with a more standard way to say "we have inputs but we
348 don 't want you to change them independent of video" which
349 will sort this mess.
350 */
351 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300352 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300353 if (vin->index > 0) break;
354 strncpy(vin->name, "PVRUSB2 Audio",14);
355 vin->capability = V4L2_AUDCAP_STEREO;
356 ret = 0;
357 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300358 break;
359 }
360
361 case VIDIOC_G_AUDIO:
362 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300363 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
364 struct v4l2_audio *vin = arg;
365 memset(vin,0,sizeof(*vin));
366 vin->index = 0;
367 strncpy(vin->name, "PVRUSB2 Audio",14);
368 vin->capability = V4L2_AUDCAP_STEREO;
369 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300370 break;
371 }
372
Mike Iselyd8554972006-06-26 20:58:46 -0300373 case VIDIOC_G_TUNER:
374 {
375 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300376
Michael Krufky8d364362007-01-22 02:17:55 -0300377 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300378
Mike Isely18103c572007-01-20 00:09:47 -0300379 pvr2_hdw_execute_tuner_poll(hdw);
380 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300381 break;
382 }
383
384 case VIDIOC_S_TUNER:
385 {
386 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
387
388 if (vt->index != 0)
389 break;
390
391 ret = pvr2_ctrl_set_value(
392 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
393 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300394 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300395 }
396
397 case VIDIOC_S_FREQUENCY:
398 {
399 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300400 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300401 struct v4l2_tuner vt;
402 int cur_input;
403 struct pvr2_ctrl *ctrlp;
404 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
405 if (ret != 0) break;
406 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
407 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
408 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300409 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300410 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
411 pvr2_ctrl_set_value(ctrlp,
412 PVR2_CVAL_INPUT_RADIO);
413 }
414 } else {
415 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
416 pvr2_ctrl_set_value(ctrlp,
417 PVR2_CVAL_INPUT_TV);
418 }
419 }
420 fv = vf->frequency;
421 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300422 fv = (fv * 125) / 2;
423 } else {
424 fv = fv * 62500;
425 }
Mike Iselyd8554972006-06-26 20:58:46 -0300426 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300427 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300428 break;
429 }
430
431 case VIDIOC_G_FREQUENCY:
432 {
433 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
434 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300435 int cur_input;
436 struct v4l2_tuner vt;
437 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
438 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300439 ret = pvr2_ctrl_get_value(
440 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
441 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300442 if (ret != 0) break;
443 pvr2_ctrl_get_value(
444 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
445 &cur_input);
446 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300447 vf->type = V4L2_TUNER_RADIO;
448 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300449 vf->type = V4L2_TUNER_ANALOG_TV;
450 }
Mike Isely18103c572007-01-20 00:09:47 -0300451 if (vt.capability & V4L2_TUNER_CAP_LOW) {
452 val = (val * 2) / 125;
453 } else {
454 val /= 62500;
455 }
456 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300457 break;
458 }
459
460 case VIDIOC_ENUM_FMT:
461 {
462 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
463
464 /* Only one format is supported : mpeg.*/
465 if (fd->index != 0)
466 break;
467
468 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
469 ret = 0;
470 break;
471 }
472
473 case VIDIOC_G_FMT:
474 {
475 struct v4l2_format *vf = (struct v4l2_format *)arg;
476 int val;
477 switch(vf->type) {
478 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
479 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
480 sizeof(struct v4l2_format));
481 val = 0;
482 pvr2_ctrl_get_value(
483 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
484 &val);
485 vf->fmt.pix.width = val;
486 val = 0;
487 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300488 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
489 &val);
490 vf->fmt.pix.height = val;
491 ret = 0;
492 break;
493 case V4L2_BUF_TYPE_VBI_CAPTURE:
494 // ????? Still need to figure out to do VBI correctly
495 ret = -EINVAL;
496 break;
497 default:
498 ret = -EINVAL;
499 break;
500 }
501 break;
502 }
503
504 case VIDIOC_TRY_FMT:
505 case VIDIOC_S_FMT:
506 {
507 struct v4l2_format *vf = (struct v4l2_format *)arg;
508
509 ret = 0;
510 switch(vf->type) {
511 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300512 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300513 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300514 int h = vf->fmt.pix.height;
515 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300516 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
517 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300518
Mike Iselye95a1912006-08-08 09:10:07 -0300519 lmin = pvr2_ctrl_get_min(hcp);
520 lmax = pvr2_ctrl_get_max(hcp);
Mike Isely26dd1c572008-08-31 20:55:03 -0300521 pvr2_ctrl_get_def(hcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300522 if (w == -1) {
523 w = ldef;
524 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300525 w = lmin;
526 } else if (w > lmax) {
527 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300528 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300529 lmin = pvr2_ctrl_get_min(vcp);
530 lmax = pvr2_ctrl_get_max(vcp);
Mike Isely26dd1c572008-08-31 20:55:03 -0300531 pvr2_ctrl_get_def(vcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300532 if (h == -1) {
533 h = ldef;
534 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300535 h = lmin;
536 } else if (h > lmax) {
537 h = lmax;
538 }
Mike Iselyd8554972006-06-26 20:58:46 -0300539
540 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
541 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300542 vf->fmt.pix.width = w;
543 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300544
545 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300546 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
547 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300548 }
549 } break;
550 case V4L2_BUF_TYPE_VBI_CAPTURE:
551 // ????? Still need to figure out to do VBI correctly
552 ret = -EINVAL;
553 break;
554 default:
555 ret = -EINVAL;
556 break;
557 }
558 break;
559 }
560
561 case VIDIOC_STREAMON:
562 {
Joe Perches108bdd72010-04-05 16:05:39 -0300563 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300564 /* No stream defined for this node. This means
565 that we're not currently allowed to stream from
566 this node. */
567 ret = -EPERM;
568 break;
569 }
Joe Perches108bdd72010-04-05 16:05:39 -0300570 ret = pvr2_hdw_set_stream_type(hdw,pdi->config);
Mike Iselyd8554972006-06-26 20:58:46 -0300571 if (ret < 0) return ret;
572 ret = pvr2_hdw_set_streaming(hdw,!0);
573 break;
574 }
575
576 case VIDIOC_STREAMOFF:
577 {
Joe Perches108bdd72010-04-05 16:05:39 -0300578 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300579 /* No stream defined for this node. This means
580 that we're not currently allowed to stream from
581 this node. */
582 ret = -EPERM;
583 break;
584 }
Mike Iselyd8554972006-06-26 20:58:46 -0300585 ret = pvr2_hdw_set_streaming(hdw,0);
586 break;
587 }
588
589 case VIDIOC_QUERYCTRL:
590 {
591 struct pvr2_ctrl *cptr;
Mike Isely26dd1c572008-08-31 20:55:03 -0300592 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300593 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
594 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300595 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
596 cptr = pvr2_hdw_get_ctrl_nextv4l(
597 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
598 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
599 } else {
600 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
601 }
Mike Iselyd8554972006-06-26 20:58:46 -0300602 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300603 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300604 "QUERYCTRL id=0x%x not implemented here",
605 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300606 ret = -EINVAL;
607 break;
608 }
609
Mike Iselya761f432006-06-25 20:04:44 -0300610 pvr2_trace(PVR2_TRACE_V4LIOCTL,
611 "QUERYCTRL id=0x%x mapping name=%s (%s)",
612 vc->id,pvr2_ctrl_get_name(cptr),
613 pvr2_ctrl_get_desc(cptr));
614 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
615 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Isely26dd1c572008-08-31 20:55:03 -0300616 pvr2_ctrl_get_def(cptr, &val);
617 vc->default_value = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300618 switch (pvr2_ctrl_get_type(cptr)) {
619 case pvr2_ctl_enum:
620 vc->type = V4L2_CTRL_TYPE_MENU;
621 vc->minimum = 0;
622 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
623 vc->step = 1;
624 break;
Mike Isely33213962006-06-25 20:04:40 -0300625 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300626 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300627 vc->minimum = 0;
628 vc->maximum = 1;
629 vc->step = 1;
630 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300631 case pvr2_ctl_int:
632 vc->type = V4L2_CTRL_TYPE_INTEGER;
633 vc->minimum = pvr2_ctrl_get_min(cptr);
634 vc->maximum = pvr2_ctrl_get_max(cptr);
635 vc->step = 1;
636 break;
637 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300638 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300639 "QUERYCTRL id=0x%x name=%s not mappable",
640 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300641 ret = -EINVAL;
642 break;
643 }
644 break;
645 }
646
647 case VIDIOC_QUERYMENU:
648 {
649 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
650 unsigned int cnt = 0;
651 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
652 vm->index,
653 vm->name,sizeof(vm->name)-1,
654 &cnt);
655 vm->name[cnt] = 0;
656 break;
657 }
658
659 case VIDIOC_G_CTRL:
660 {
661 struct v4l2_control *vc = (struct v4l2_control *)arg;
662 int val = 0;
663 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
664 &val);
665 vc->value = val;
666 break;
667 }
668
669 case VIDIOC_S_CTRL:
670 {
671 struct v4l2_control *vc = (struct v4l2_control *)arg;
672 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
673 vc->value);
674 break;
675 }
676
Mike Isely1d9f8462006-06-25 20:04:58 -0300677 case VIDIOC_G_EXT_CTRLS:
678 {
679 struct v4l2_ext_controls *ctls =
680 (struct v4l2_ext_controls *)arg;
681 struct v4l2_ext_control *ctrl;
682 unsigned int idx;
683 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300684 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300685 for (idx = 0; idx < ctls->count; idx++) {
686 ctrl = ctls->controls + idx;
687 ret = pvr2_ctrl_get_value(
688 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
689 if (ret) {
690 ctls->error_idx = idx;
691 break;
692 }
693 /* Ensure that if read as a 64 bit value, the user
694 will still get a hopefully sane value */
695 ctrl->value64 = 0;
696 ctrl->value = val;
697 }
698 break;
699 }
700
701 case VIDIOC_S_EXT_CTRLS:
702 {
703 struct v4l2_ext_controls *ctls =
704 (struct v4l2_ext_controls *)arg;
705 struct v4l2_ext_control *ctrl;
706 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300707 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300708 for (idx = 0; idx < ctls->count; idx++) {
709 ctrl = ctls->controls + idx;
710 ret = pvr2_ctrl_set_value(
711 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
712 ctrl->value);
713 if (ret) {
714 ctls->error_idx = idx;
715 break;
716 }
717 }
718 break;
719 }
720
721 case VIDIOC_TRY_EXT_CTRLS:
722 {
723 struct v4l2_ext_controls *ctls =
724 (struct v4l2_ext_controls *)arg;
725 struct v4l2_ext_control *ctrl;
726 struct pvr2_ctrl *pctl;
727 unsigned int idx;
728 /* For the moment just validate that the requested control
729 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300730 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300731 for (idx = 0; idx < ctls->count; idx++) {
732 ctrl = ctls->controls + idx;
733 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
734 if (!pctl) {
735 ret = -EINVAL;
736 ctls->error_idx = idx;
737 break;
738 }
739 }
740 break;
741 }
742
Mike Isely432907f2008-08-31 21:02:20 -0300743 case VIDIOC_CROPCAP:
744 {
745 struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
746 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
747 ret = -EINVAL;
748 break;
749 }
750 ret = pvr2_hdw_get_cropcap(hdw, cap);
751 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
752 break;
753 }
754 case VIDIOC_G_CROP:
755 {
756 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
757 int val = 0;
758 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
759 ret = -EINVAL;
760 break;
761 }
762 ret = pvr2_ctrl_get_value(
763 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
764 if (ret != 0) {
765 ret = -EINVAL;
766 break;
767 }
768 crop->c.left = val;
769 ret = pvr2_ctrl_get_value(
770 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
771 if (ret != 0) {
772 ret = -EINVAL;
773 break;
774 }
775 crop->c.top = val;
776 ret = pvr2_ctrl_get_value(
777 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
778 if (ret != 0) {
779 ret = -EINVAL;
780 break;
781 }
782 crop->c.width = val;
783 ret = pvr2_ctrl_get_value(
784 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
785 if (ret != 0) {
786 ret = -EINVAL;
787 break;
788 }
789 crop->c.height = val;
790 }
791 case VIDIOC_S_CROP:
792 {
793 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
Mike Isely432907f2008-08-31 21:02:20 -0300794 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
795 ret = -EINVAL;
796 break;
797 }
Mike Isely432907f2008-08-31 21:02:20 -0300798 ret = pvr2_ctrl_set_value(
799 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
800 crop->c.left);
801 if (ret != 0) {
802 ret = -EINVAL;
803 break;
804 }
805 ret = pvr2_ctrl_set_value(
806 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
807 crop->c.top);
808 if (ret != 0) {
809 ret = -EINVAL;
810 break;
811 }
812 ret = pvr2_ctrl_set_value(
813 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
814 crop->c.width);
815 if (ret != 0) {
816 ret = -EINVAL;
817 break;
818 }
819 ret = pvr2_ctrl_set_value(
820 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
821 crop->c.height);
822 if (ret != 0) {
823 ret = -EINVAL;
824 break;
825 }
826 }
Mike Iselyd8554972006-06-26 20:58:46 -0300827 case VIDIOC_LOG_STATUS:
828 {
Mike Iselyd8554972006-06-26 20:58:46 -0300829 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300830 ret = 0;
831 break;
832 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300833#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300834 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300835 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300836 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300837 u64 val;
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300838 struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300839 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300840 ret = pvr2_hdw_register_access(
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300841 hdw, &req->match, req->reg,
842 cmd == VIDIOC_DBG_S_REGISTER, &val);
Trent Piepho52ebc762007-01-23 22:38:13 -0300843 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300844 break;
845 }
846#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300847
848 default :
Mauro Carvalho Chehab7a286cc2011-06-26 10:18:03 -0300849 ret = -ENOTTY;
Hans Verkuil08af2452010-12-24 10:33:19 -0300850 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300851 }
852
853 pvr2_hdw_commit_ctl(hdw);
854
855 if (ret < 0) {
856 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300857 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300858 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300859 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300860 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
861 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300862 "pvr2_v4l2_do_ioctl failure, ret=%ld"
863 " command was:", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300864 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
865 cmd);
866 }
867 }
868 } else {
869 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300870 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
871 ret, ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300872 }
873 return ret;
874}
875
Mike Iselyd8554972006-06-26 20:58:46 -0300876static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
877{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300878 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300879 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300880 char msg[80];
881 unsigned int mcnt;
882
883 /* Construct the unregistration message *before* we actually
884 perform the unregistration step. By doing it this way we don't
885 have to worry about potentially touching deleted resources. */
886 mcnt = scnprintf(msg, sizeof(msg) - 1,
887 "pvrusb2: unregistered device %s [%s]",
888 video_device_node_name(&dip->devbase),
889 pvr2_config_get_name(cfg));
890 msg[mcnt] = 0;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300891
Mike Isely16eb40d2006-12-30 18:27:32 -0300892 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300893
894 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300895 dip->v4lp = NULL;
896 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300897
898 /* Actual deallocation happens later when all internal references
899 are gone. */
900 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300901
Mike Iselyd72baad2010-05-15 00:15:38 -0300902 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300903
Mike Iselyd8554972006-06-26 20:58:46 -0300904}
905
906
Mike Isely4a89baa2009-10-12 00:13:28 -0300907static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
908{
909 if (!dip) return;
910 if (!dip->devbase.parent) return;
911 dip->devbase.parent = NULL;
912 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
913}
914
915
Mike Iselyd8554972006-06-26 20:58:46 -0300916static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
917{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300918 if (vp->dev_video) {
919 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000920 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300921 }
922 if (vp->dev_radio) {
923 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000924 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300925 }
Mike Iselyd8554972006-06-26 20:58:46 -0300926
927 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
928 pvr2_channel_done(&vp->channel);
929 kfree(vp);
930}
931
932
Mike Isely75910052006-09-23 22:30:50 -0300933static void pvr2_video_device_release(struct video_device *vdev)
934{
935 struct pvr2_v4l2_dev *dev;
936 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
937 kfree(dev);
938}
939
940
Adrian Bunk07e337e2006-06-30 11:30:20 -0300941static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300942{
943 struct pvr2_v4l2 *vp;
944 vp = container_of(chp,struct pvr2_v4l2,channel);
945 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300946 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
947 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300948 if (vp->vfirst) return;
949 pvr2_v4l2_destroy_no_lock(vp);
950}
951
952
Hans Verkuil069b7472008-12-30 07:04:34 -0300953static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300954 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300955{
956
Hans Verkuilf473bf72008-11-01 08:25:11 -0300957 return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
Mike Iselyd8554972006-06-26 20:58:46 -0300958}
959
960
Hans Verkuilbec43662008-12-30 06:58:20 -0300961static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300962{
963 struct pvr2_v4l2_fh *fhp = file->private_data;
964 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300965 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300966
967 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
968
969 if (fhp->rhp) {
970 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300971 pvr2_hdw_set_streaming(hdw,0);
972 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300973 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300974 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300975 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300976 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300977
Hans Verkuilffb48772010-05-01 08:03:24 -0300978 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300979 file->private_data = NULL;
980
Mike Isely794b1602008-04-22 14:45:45 -0300981 if (fhp->vnext) {
982 fhp->vnext->vprev = fhp->vprev;
983 } else {
984 vp->vlast = fhp->vprev;
985 }
986 if (fhp->vprev) {
987 fhp->vprev->vnext = fhp->vnext;
988 } else {
989 vp->vfirst = fhp->vnext;
990 }
991 fhp->vnext = NULL;
992 fhp->vprev = NULL;
993 fhp->vhead = NULL;
994 pvr2_channel_done(&fhp->channel);
995 pvr2_trace(PVR2_TRACE_STRUCT,
996 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300997 if (fhp->input_map) {
998 kfree(fhp->input_map);
999 fhp->input_map = NULL;
1000 }
Mike Isely794b1602008-04-22 14:45:45 -03001001 kfree(fhp);
1002 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1003 pvr2_v4l2_destroy_no_lock(vp);
1004 }
Mike Iselyd8554972006-06-26 20:58:46 -03001005 return 0;
1006}
1007
1008
Hans Verkuilbec43662008-12-30 06:58:20 -03001009static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001010{
Mike Isely75910052006-09-23 22:30:50 -03001011 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001012 struct pvr2_v4l2_fh *fhp;
1013 struct pvr2_v4l2 *vp;
1014 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001015 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001016 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001017 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001018
Mike Isely75910052006-09-23 22:30:50 -03001019 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001020
1021 vp = dip->v4lp;
1022 hdw = vp->channel.hdw;
1023
1024 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1025
1026 if (!pvr2_hdw_dev_ok(hdw)) {
1027 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1028 "pvr2_v4l2_open: hardware not ready");
1029 return -EIO;
1030 }
1031
Mike Isely4b85dee2007-01-20 00:03:32 -03001032 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001033 if (!fhp) {
1034 return -ENOMEM;
1035 }
Mike Iselyd8554972006-06-26 20:58:46 -03001036
1037 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001038 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001039
Mike Isely794b1602008-04-22 14:45:45 -03001040 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1041 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001042
Mike Isely1cb03b72008-04-21 03:47:43 -03001043 if (dip->v4l_type == VFL_TYPE_RADIO) {
1044 /* Opening device as a radio, legal input selection subset
1045 is just the radio. */
1046 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1047 } else {
1048 /* Opening the main V4L device, legal input selection
1049 subset includes all analog inputs. */
1050 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1051 (1 << PVR2_CVAL_INPUT_TV) |
1052 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1053 (1 << PVR2_CVAL_INPUT_SVIDEO));
1054 }
1055 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1056 if (ret) {
1057 pvr2_channel_done(&fhp->channel);
1058 pvr2_trace(PVR2_TRACE_STRUCT,
1059 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1060 fhp);
1061
1062 kfree(fhp);
1063 return ret;
1064 }
1065
Mike Iselye57b1c82008-04-21 03:52:34 -03001066 input_mask &= pvr2_hdw_get_input_available(hdw);
1067 input_cnt = 0;
1068 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1069 if (input_mask & (1 << idx)) input_cnt++;
1070 }
1071 fhp->input_cnt = input_cnt;
1072 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1073 if (!fhp->input_map) {
1074 pvr2_channel_done(&fhp->channel);
1075 pvr2_trace(PVR2_TRACE_STRUCT,
1076 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1077 fhp);
1078 kfree(fhp);
1079 return -ENOMEM;
1080 }
1081 input_cnt = 0;
1082 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1083 if (!(input_mask & (1 << idx))) continue;
1084 fhp->input_map[input_cnt++] = idx;
1085 }
1086
Mike Isely794b1602008-04-22 14:45:45 -03001087 fhp->vnext = NULL;
1088 fhp->vprev = vp->vlast;
1089 if (vp->vlast) {
1090 vp->vlast->vnext = fhp;
1091 } else {
1092 vp->vfirst = fhp;
1093 }
1094 vp->vlast = fhp;
1095 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001096
Mike Iselyd8554972006-06-26 20:58:46 -03001097 fhp->file = file;
1098 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001099 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001100
1101 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1102
1103 return 0;
1104}
1105
1106
1107static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1108{
1109 wake_up(&fhp->wait_data);
1110}
1111
1112static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1113{
1114 int ret;
1115 struct pvr2_stream *sp;
1116 struct pvr2_hdw *hdw;
1117 if (fh->rhp) return 0;
1118
Joe Perches108bdd72010-04-05 16:05:39 -03001119 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001120 /* No stream defined for this node. This means that we're
1121 not currently allowed to stream from this node. */
1122 return -EPERM;
1123 }
1124
Mike Iselyd8554972006-06-26 20:58:46 -03001125 /* First read() attempt. Try to claim the stream and start
1126 it... */
1127 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001128 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001129 /* Someone else must already have it */
1130 return ret;
1131 }
1132
Joe Perches108bdd72010-04-05 16:05:39 -03001133 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001134 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001135 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001136 return -ENOMEM;
1137 }
1138
1139 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001140 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001141 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001142 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001143 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1144 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001145}
1146
1147
1148static ssize_t pvr2_v4l2_read(struct file *file,
1149 char __user *buff, size_t count, loff_t *ppos)
1150{
1151 struct pvr2_v4l2_fh *fh = file->private_data;
1152 int ret;
1153
1154 if (fh->fw_mode_flag) {
1155 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1156 char *tbuf;
1157 int c1,c2;
1158 int tcnt = 0;
1159 unsigned int offs = *ppos;
1160
1161 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1162 if (!tbuf) return -ENOMEM;
1163
1164 while (count) {
1165 c1 = count;
1166 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1167 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1168 if (c2 < 0) {
1169 tcnt = c2;
1170 break;
1171 }
1172 if (!c2) break;
1173 if (copy_to_user(buff,tbuf,c2)) {
1174 tcnt = -EFAULT;
1175 break;
1176 }
1177 offs += c2;
1178 tcnt += c2;
1179 buff += c2;
1180 count -= c2;
1181 *ppos += c2;
1182 }
1183 kfree(tbuf);
1184 return tcnt;
1185 }
1186
1187 if (!fh->rhp) {
1188 ret = pvr2_v4l2_iosetup(fh);
1189 if (ret) {
1190 return ret;
1191 }
1192 }
1193
1194 for (;;) {
1195 ret = pvr2_ioread_read(fh->rhp,buff,count);
1196 if (ret >= 0) break;
1197 if (ret != -EAGAIN) break;
1198 if (file->f_flags & O_NONBLOCK) break;
1199 /* Doing blocking I/O. Wait here. */
1200 ret = wait_event_interruptible(
1201 fh->wait_data,
1202 pvr2_ioread_avail(fh->rhp) >= 0);
1203 if (ret < 0) break;
1204 }
1205
1206 return ret;
1207}
1208
1209
1210static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1211{
1212 unsigned int mask = 0;
1213 struct pvr2_v4l2_fh *fh = file->private_data;
1214 int ret;
1215
1216 if (fh->fw_mode_flag) {
1217 mask |= POLLIN | POLLRDNORM;
1218 return mask;
1219 }
1220
1221 if (!fh->rhp) {
1222 ret = pvr2_v4l2_iosetup(fh);
1223 if (ret) return POLLERR;
1224 }
1225
1226 poll_wait(file,&fh->wait_data,wait);
1227
1228 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1229 mask |= POLLIN | POLLRDNORM;
1230 }
1231
1232 return mask;
1233}
1234
1235
Hans Verkuilbec43662008-12-30 06:58:20 -03001236static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001237 .owner = THIS_MODULE,
1238 .open = pvr2_v4l2_open,
1239 .release = pvr2_v4l2_release,
1240 .read = pvr2_v4l2_read,
1241 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001242 .poll = pvr2_v4l2_poll,
1243};
1244
1245
Mike Iselyd8554972006-06-26 20:58:46 -03001246static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001247 .fops = &vdev_fops,
1248};
1249
1250
1251static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1252 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001253 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001254{
Mike Isely4a89baa2009-10-12 00:13:28 -03001255 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001256 int mindevnum;
1257 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001258 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001259 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001260
Mike Isely4a89baa2009-10-12 00:13:28 -03001261 usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001262 dip->v4l_type = v4l_type;
1263 switch (v4l_type) {
1264 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001265 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001266 dip->config = pvr2_config_mpeg;
1267 dip->minor_type = pvr2_v4l_type_video;
1268 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001269 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001270 pr_err(KBUILD_MODNAME
1271 ": Failed to set up pvrusb2 v4l video dev"
1272 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001273 return;
1274 }
Mike Iselyd8554972006-06-26 20:58:46 -03001275 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001276 case VFL_TYPE_VBI:
1277 dip->config = pvr2_config_vbi;
1278 dip->minor_type = pvr2_v4l_type_vbi;
1279 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001280 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001281 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001282 dip->stream = &vp->channel.mc_head->video_stream;
1283 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001284 dip->minor_type = pvr2_v4l_type_radio;
1285 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001286 break;
1287 default:
1288 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001289 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1290 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001291 return;
1292 }
1293
Mike Isely75910052006-09-23 22:30:50 -03001294 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1295 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001296
1297 mindevnum = -1;
1298 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001299 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1300 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001301 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001302 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001303 if ((video_register_device(&dip->devbase,
1304 dip->v4l_type, mindevnum) < 0) &&
1305 (video_register_device(&dip->devbase,
1306 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001307 pr_err(KBUILD_MODNAME
1308 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001309 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001310
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001311 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1312 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001313 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001314
Mike Iselyd8554972006-06-26 20:58:46 -03001315 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001316 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001317}
1318
1319
1320struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1321{
1322 struct pvr2_v4l2 *vp;
1323
Mike Isely4b85dee2007-01-20 00:03:32 -03001324 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001325 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001326 pvr2_channel_init(&vp->channel,mnp);
1327 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1328
1329 vp->channel.check_func = pvr2_v4l2_internal_check;
1330
1331 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001332 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1333 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001334 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001335 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1336 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001337 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1338 if (!vp->dev_radio) goto fail;
1339 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1340 }
Mike Iselyd8554972006-06-26 20:58:46 -03001341
1342 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001343 fail:
1344 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1345 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001346 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001347}
1348
1349/*
1350 Stuff for Emacs to see, in order to encourage consistent editing style:
1351 *** Local Variables: ***
1352 *** mode: c ***
1353 *** fill-column: 75 ***
1354 *** tab-width: 8 ***
1355 *** c-basic-offset: 8 ***
1356 *** End: ***
1357 */