blob: 0d029da07e6b9b516660a21ba1970163f06f5f17 [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>
Mike Isely43e06022006-09-23 23:47:50 -030032#include <media/v4l2-dev.h>
Mike Iselyd8554972006-06-26 20:58:46 -030033#include <media/v4l2-common.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030034#include <media/v4l2-ioctl.h>
Mike Iselyd8554972006-06-26 20:58:46 -030035
36struct pvr2_v4l2_dev;
37struct pvr2_v4l2_fh;
38struct pvr2_v4l2;
39
Mike Iselyd8554972006-06-26 20:58:46 -030040struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030041 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030042 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030043 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030044 /* Information about this device: */
45 enum pvr2_config config; /* Expected stream format */
46 int v4l_type; /* V4L defined type for this device node */
47 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030048};
49
50struct pvr2_v4l2_fh {
51 struct pvr2_channel channel;
Joe Perches108bdd72010-04-05 16:05:39 -030052 struct pvr2_v4l2_dev *pdi;
Mike Iselyd8554972006-06-26 20:58:46 -030053 enum v4l2_priority prio;
54 struct pvr2_ioread *rhp;
55 struct file *file;
56 struct pvr2_v4l2 *vhead;
57 struct pvr2_v4l2_fh *vnext;
58 struct pvr2_v4l2_fh *vprev;
59 wait_queue_head_t wait_data;
60 int fw_mode_flag;
Mike Iselye57b1c82008-04-21 03:52:34 -030061 /* Map contiguous ordinal value to input id */
62 unsigned char *input_map;
63 unsigned int input_cnt;
Mike Iselyd8554972006-06-26 20:58:46 -030064};
65
66struct pvr2_v4l2 {
67 struct pvr2_channel channel;
68 struct pvr2_v4l2_fh *vfirst;
69 struct pvr2_v4l2_fh *vlast;
70
71 struct v4l2_prio_state prio;
72
Mike Isely0f0f2572006-12-27 23:19:42 -030073 /* streams - Note that these must be separately, individually,
74 * allocated pointers. This is because the v4l core is going to
75 * manage their deletion - separately, individually... */
76 struct pvr2_v4l2_dev *dev_video;
77 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030078};
79
80static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
81module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030082MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
83static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
84module_param_array(radio_nr, int, NULL, 0444);
85MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
86static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
87module_param_array(vbi_nr, int, NULL, 0444);
88MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030089
Adrian Bunk07e337e2006-06-30 11:30:20 -030090static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030091 .driver = "pvrusb2",
92 .card = "Hauppauge WinTV pvr-usb2",
93 .bus_info = "usb",
Mauro Carvalho Chehab083774d2011-06-25 13:34:24 -030094 .version = LINUX_VERSION_CODE,
Mike Iselyd166b022009-01-14 04:21:29 -030095 .capabilities = (V4L2_CAP_VIDEO_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030096 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030097 V4L2_CAP_READWRITE),
98 .reserved = {0,0,0,0}
99};
100
Adrian Bunk07e337e2006-06-30 11:30:20 -0300101static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300102 {
103 .index = 0,
104 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
105 .flags = V4L2_FMT_FLAG_COMPRESSED,
106 .description = "MPEG1/2",
107 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
108 // breaks when I do that.
109 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
110 .reserved = { 0, 0, 0, 0 }
111 }
112};
113
114#define PVR_FORMAT_PIX 0
115#define PVR_FORMAT_VBI 1
116
Adrian Bunk07e337e2006-06-30 11:30:20 -0300117static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300118 [PVR_FORMAT_PIX] = {
119 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
120 .fmt = {
121 .pix = {
122 .width = 720,
123 .height = 576,
124 // This should really be V4L2_PIX_FMT_MPEG,
125 // but xawtv breaks when I do that.
126 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
127 .field = V4L2_FIELD_INTERLACED,
128 .bytesperline = 0, // doesn't make sense
129 // here
130 //FIXME : Don't know what to put here...
131 .sizeimage = (32*1024),
132 .colorspace = 0, // doesn't make sense here
133 .priv = 0
134 }
135 }
136 },
137 [PVR_FORMAT_VBI] = {
138 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
139 .fmt = {
140 .vbi = {
141 .sampling_rate = 27000000,
142 .offset = 248,
143 .samples_per_line = 1443,
144 .sample_format = V4L2_PIX_FMT_GREY,
145 .start = { 0, 0 },
146 .count = { 0, 0 },
147 .flags = 0,
148 .reserved = { 0, 0 }
149 }
150 }
151 }
152};
153
Mike Isely16eb40d2006-12-30 18:27:32 -0300154
Mike Iselyd8554972006-06-26 20:58:46 -0300155/*
156 * pvr_ioctl()
157 *
158 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
159 *
160 */
Hans Verkuil069b7472008-12-30 07:04:34 -0300161static long pvr2_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300162{
163 struct pvr2_v4l2_fh *fh = file->private_data;
164 struct pvr2_v4l2 *vp = fh->vhead;
Joe Perches108bdd72010-04-05 16:05:39 -0300165 struct pvr2_v4l2_dev *pdi = fh->pdi;
Mike Iselyd8554972006-06-26 20:58:46 -0300166 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
Hans Verkuil069b7472008-12-30 07:04:34 -0300167 long ret = -EINVAL;
Mike Iselyd8554972006-06-26 20:58:46 -0300168
169 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
170 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
171 }
172
173 if (!pvr2_hdw_dev_ok(hdw)) {
174 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
175 "ioctl failed - bad or no context");
176 return -EFAULT;
177 }
178
179 /* check priority */
180 switch (cmd) {
181 case VIDIOC_S_CTRL:
182 case VIDIOC_S_STD:
183 case VIDIOC_S_INPUT:
184 case VIDIOC_S_TUNER:
185 case VIDIOC_S_FREQUENCY:
Hans Verkuilffb48772010-05-01 08:03:24 -0300186 ret = v4l2_prio_check(&vp->prio, fh->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300187 if (ret)
188 return ret;
189 }
190
191 switch (cmd) {
192 case VIDIOC_QUERYCAP:
193 {
194 struct v4l2_capability *cap = arg;
195
196 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300197 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
198 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300199 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300200
201 ret = 0;
202 break;
203 }
204
205 case VIDIOC_G_PRIORITY:
206 {
207 enum v4l2_priority *p = arg;
208
209 *p = v4l2_prio_max(&vp->prio);
210 ret = 0;
211 break;
212 }
213
214 case VIDIOC_S_PRIORITY:
215 {
216 enum v4l2_priority *prio = arg;
217
218 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
219 break;
220 }
221
222 case VIDIOC_ENUMSTD:
223 {
224 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
225 int idx = vs->index;
226 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
227 break;
228 }
229
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300230 case VIDIOC_QUERYSTD:
231 {
232 v4l2_std_id *std = arg;
233 ret = pvr2_hdw_get_detected_std(hdw, std);
234 break;
235 }
236
Mike Iselyd8554972006-06-26 20:58:46 -0300237 case VIDIOC_G_STD:
238 {
239 int val = 0;
240 ret = pvr2_ctrl_get_value(
241 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
242 *(v4l2_std_id *)arg = val;
243 break;
244 }
245
246 case VIDIOC_S_STD:
247 {
248 ret = pvr2_ctrl_set_value(
249 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
250 *(v4l2_std_id *)arg);
251 break;
252 }
253
254 case VIDIOC_ENUMINPUT:
255 {
256 struct pvr2_ctrl *cptr;
257 struct v4l2_input *vi = (struct v4l2_input *)arg;
258 struct v4l2_input tmp;
259 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300260 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300261
262 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
263
264 memset(&tmp,0,sizeof(tmp));
265 tmp.index = vi->index;
266 ret = 0;
Roel Kluin223ffe52009-05-02 16:38:47 -0300267 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300268 ret = -EINVAL;
269 break;
270 }
Mike Iselye57b1c82008-04-21 03:52:34 -0300271 val = fh->input_map[vi->index];
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300272 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300273 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300274 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300275 case PVR2_CVAL_INPUT_RADIO:
276 tmp.type = V4L2_INPUT_TYPE_TUNER;
277 break;
278 case PVR2_CVAL_INPUT_SVIDEO:
279 case PVR2_CVAL_INPUT_COMPOSITE:
280 tmp.type = V4L2_INPUT_TYPE_CAMERA;
281 break;
282 default:
283 ret = -EINVAL;
284 break;
285 }
286 if (ret < 0) break;
287
288 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300289 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300290 tmp.name,sizeof(tmp.name)-1,&cnt);
291 tmp.name[cnt] = 0;
292
293 /* Don't bother with audioset, since this driver currently
294 always switches the audio whenever the video is
295 switched. */
296
297 /* Handling std is a tougher problem. It doesn't make
298 sense in cases where a device might be multi-standard.
299 We could just copy out the current value for the
300 standard, but it can change over time. For now just
301 leave it zero. */
302
303 memcpy(vi, &tmp, sizeof(tmp));
304
305 ret = 0;
306 break;
307 }
308
309 case VIDIOC_G_INPUT:
310 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300311 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300312 struct pvr2_ctrl *cptr;
313 struct v4l2_input *vi = (struct v4l2_input *)arg;
314 int val;
315 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
316 val = 0;
317 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300318 vi->index = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300319 for (idx = 0; idx < fh->input_cnt; idx++) {
320 if (fh->input_map[idx] == val) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300321 vi->index = idx;
322 break;
323 }
324 }
Mike Iselyd8554972006-06-26 20:58:46 -0300325 break;
326 }
327
328 case VIDIOC_S_INPUT:
329 {
330 struct v4l2_input *vi = (struct v4l2_input *)arg;
Roel Kluin223ffe52009-05-02 16:38:47 -0300331 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300332 ret = -ERANGE;
333 break;
334 }
Mike Iselyd8554972006-06-26 20:58:46 -0300335 ret = pvr2_ctrl_set_value(
336 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselye57b1c82008-04-21 03:52:34 -0300337 fh->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300338 break;
339 }
340
341 case VIDIOC_ENUMAUDIO:
342 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300343 /* pkt: FIXME: We are returning one "fake" input here
344 which could very well be called "whatever_we_like".
345 This is for apps that want to see an audio input
346 just to feel comfortable, as well as to test if
347 it can do stereo or sth. There is actually no guarantee
348 that the actual audio input cannot change behind the app's
349 back, but most applications should not mind that either.
350
351 Hopefully, mplayer people will work with us on this (this
352 whole mess is to support mplayer pvr://), or Hans will come
353 up with a more standard way to say "we have inputs but we
354 don 't want you to change them independent of video" which
355 will sort this mess.
356 */
357 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300358 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300359 if (vin->index > 0) break;
360 strncpy(vin->name, "PVRUSB2 Audio",14);
361 vin->capability = V4L2_AUDCAP_STEREO;
362 ret = 0;
363 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300364 break;
365 }
366
367 case VIDIOC_G_AUDIO:
368 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300369 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
370 struct v4l2_audio *vin = arg;
371 memset(vin,0,sizeof(*vin));
372 vin->index = 0;
373 strncpy(vin->name, "PVRUSB2 Audio",14);
374 vin->capability = V4L2_AUDCAP_STEREO;
375 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300376 break;
377 }
378
Mike Iselyd8554972006-06-26 20:58:46 -0300379 case VIDIOC_G_TUNER:
380 {
381 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300382
Michael Krufky8d364362007-01-22 02:17:55 -0300383 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300384
Mike Isely18103c52007-01-20 00:09:47 -0300385 pvr2_hdw_execute_tuner_poll(hdw);
386 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300387 break;
388 }
389
390 case VIDIOC_S_TUNER:
391 {
392 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
393
394 if (vt->index != 0)
395 break;
396
397 ret = pvr2_ctrl_set_value(
398 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
399 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300400 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300401 }
402
403 case VIDIOC_S_FREQUENCY:
404 {
405 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300406 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300407 struct v4l2_tuner vt;
408 int cur_input;
409 struct pvr2_ctrl *ctrlp;
410 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
411 if (ret != 0) break;
412 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
413 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
414 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300415 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300416 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
417 pvr2_ctrl_set_value(ctrlp,
418 PVR2_CVAL_INPUT_RADIO);
419 }
420 } else {
421 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
422 pvr2_ctrl_set_value(ctrlp,
423 PVR2_CVAL_INPUT_TV);
424 }
425 }
426 fv = vf->frequency;
427 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300428 fv = (fv * 125) / 2;
429 } else {
430 fv = fv * 62500;
431 }
Mike Iselyd8554972006-06-26 20:58:46 -0300432 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300433 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300434 break;
435 }
436
437 case VIDIOC_G_FREQUENCY:
438 {
439 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
440 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300441 int cur_input;
442 struct v4l2_tuner vt;
443 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
444 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300445 ret = pvr2_ctrl_get_value(
446 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
447 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300448 if (ret != 0) break;
449 pvr2_ctrl_get_value(
450 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
451 &cur_input);
452 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300453 vf->type = V4L2_TUNER_RADIO;
454 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300455 vf->type = V4L2_TUNER_ANALOG_TV;
456 }
Mike Isely18103c52007-01-20 00:09:47 -0300457 if (vt.capability & V4L2_TUNER_CAP_LOW) {
458 val = (val * 2) / 125;
459 } else {
460 val /= 62500;
461 }
462 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300463 break;
464 }
465
466 case VIDIOC_ENUM_FMT:
467 {
468 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
469
470 /* Only one format is supported : mpeg.*/
471 if (fd->index != 0)
472 break;
473
474 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
475 ret = 0;
476 break;
477 }
478
479 case VIDIOC_G_FMT:
480 {
481 struct v4l2_format *vf = (struct v4l2_format *)arg;
482 int val;
483 switch(vf->type) {
484 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
485 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
486 sizeof(struct v4l2_format));
487 val = 0;
488 pvr2_ctrl_get_value(
489 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
490 &val);
491 vf->fmt.pix.width = val;
492 val = 0;
493 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300494 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
495 &val);
496 vf->fmt.pix.height = val;
497 ret = 0;
498 break;
499 case V4L2_BUF_TYPE_VBI_CAPTURE:
500 // ????? Still need to figure out to do VBI correctly
501 ret = -EINVAL;
502 break;
503 default:
504 ret = -EINVAL;
505 break;
506 }
507 break;
508 }
509
510 case VIDIOC_TRY_FMT:
511 case VIDIOC_S_FMT:
512 {
513 struct v4l2_format *vf = (struct v4l2_format *)arg;
514
515 ret = 0;
516 switch(vf->type) {
517 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300518 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300519 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300520 int h = vf->fmt.pix.height;
521 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300522 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
523 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300524
Mike Iselye95a1912006-08-08 09:10:07 -0300525 lmin = pvr2_ctrl_get_min(hcp);
526 lmax = pvr2_ctrl_get_max(hcp);
Mike Isely26dd1c52008-08-31 20:55:03 -0300527 pvr2_ctrl_get_def(hcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300528 if (w == -1) {
529 w = ldef;
530 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300531 w = lmin;
532 } else if (w > lmax) {
533 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300534 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300535 lmin = pvr2_ctrl_get_min(vcp);
536 lmax = pvr2_ctrl_get_max(vcp);
Mike Isely26dd1c52008-08-31 20:55:03 -0300537 pvr2_ctrl_get_def(vcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300538 if (h == -1) {
539 h = ldef;
540 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300541 h = lmin;
542 } else if (h > lmax) {
543 h = lmax;
544 }
Mike Iselyd8554972006-06-26 20:58:46 -0300545
546 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
547 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300548 vf->fmt.pix.width = w;
549 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300550
551 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300552 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
553 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300554 }
555 } break;
556 case V4L2_BUF_TYPE_VBI_CAPTURE:
557 // ????? Still need to figure out to do VBI correctly
558 ret = -EINVAL;
559 break;
560 default:
561 ret = -EINVAL;
562 break;
563 }
564 break;
565 }
566
567 case VIDIOC_STREAMON:
568 {
Joe Perches108bdd72010-04-05 16:05:39 -0300569 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300570 /* No stream defined for this node. This means
571 that we're not currently allowed to stream from
572 this node. */
573 ret = -EPERM;
574 break;
575 }
Joe Perches108bdd72010-04-05 16:05:39 -0300576 ret = pvr2_hdw_set_stream_type(hdw,pdi->config);
Mike Iselyd8554972006-06-26 20:58:46 -0300577 if (ret < 0) return ret;
578 ret = pvr2_hdw_set_streaming(hdw,!0);
579 break;
580 }
581
582 case VIDIOC_STREAMOFF:
583 {
Joe Perches108bdd72010-04-05 16:05:39 -0300584 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300585 /* No stream defined for this node. This means
586 that we're not currently allowed to stream from
587 this node. */
588 ret = -EPERM;
589 break;
590 }
Mike Iselyd8554972006-06-26 20:58:46 -0300591 ret = pvr2_hdw_set_streaming(hdw,0);
592 break;
593 }
594
595 case VIDIOC_QUERYCTRL:
596 {
597 struct pvr2_ctrl *cptr;
Mike Isely26dd1c52008-08-31 20:55:03 -0300598 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300599 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
600 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300601 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
602 cptr = pvr2_hdw_get_ctrl_nextv4l(
603 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
604 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
605 } else {
606 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
607 }
Mike Iselyd8554972006-06-26 20:58:46 -0300608 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300609 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300610 "QUERYCTRL id=0x%x not implemented here",
611 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300612 ret = -EINVAL;
613 break;
614 }
615
Mike Iselya761f432006-06-25 20:04:44 -0300616 pvr2_trace(PVR2_TRACE_V4LIOCTL,
617 "QUERYCTRL id=0x%x mapping name=%s (%s)",
618 vc->id,pvr2_ctrl_get_name(cptr),
619 pvr2_ctrl_get_desc(cptr));
620 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
621 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Isely26dd1c52008-08-31 20:55:03 -0300622 pvr2_ctrl_get_def(cptr, &val);
623 vc->default_value = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300624 switch (pvr2_ctrl_get_type(cptr)) {
625 case pvr2_ctl_enum:
626 vc->type = V4L2_CTRL_TYPE_MENU;
627 vc->minimum = 0;
628 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
629 vc->step = 1;
630 break;
Mike Isely33213962006-06-25 20:04:40 -0300631 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300632 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300633 vc->minimum = 0;
634 vc->maximum = 1;
635 vc->step = 1;
636 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300637 case pvr2_ctl_int:
638 vc->type = V4L2_CTRL_TYPE_INTEGER;
639 vc->minimum = pvr2_ctrl_get_min(cptr);
640 vc->maximum = pvr2_ctrl_get_max(cptr);
641 vc->step = 1;
642 break;
643 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300644 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300645 "QUERYCTRL id=0x%x name=%s not mappable",
646 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300647 ret = -EINVAL;
648 break;
649 }
650 break;
651 }
652
653 case VIDIOC_QUERYMENU:
654 {
655 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
656 unsigned int cnt = 0;
657 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
658 vm->index,
659 vm->name,sizeof(vm->name)-1,
660 &cnt);
661 vm->name[cnt] = 0;
662 break;
663 }
664
665 case VIDIOC_G_CTRL:
666 {
667 struct v4l2_control *vc = (struct v4l2_control *)arg;
668 int val = 0;
669 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
670 &val);
671 vc->value = val;
672 break;
673 }
674
675 case VIDIOC_S_CTRL:
676 {
677 struct v4l2_control *vc = (struct v4l2_control *)arg;
678 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
679 vc->value);
680 break;
681 }
682
Mike Isely1d9f8462006-06-25 20:04:58 -0300683 case VIDIOC_G_EXT_CTRLS:
684 {
685 struct v4l2_ext_controls *ctls =
686 (struct v4l2_ext_controls *)arg;
687 struct v4l2_ext_control *ctrl;
688 unsigned int idx;
689 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300690 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300691 for (idx = 0; idx < ctls->count; idx++) {
692 ctrl = ctls->controls + idx;
693 ret = pvr2_ctrl_get_value(
694 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
695 if (ret) {
696 ctls->error_idx = idx;
697 break;
698 }
699 /* Ensure that if read as a 64 bit value, the user
700 will still get a hopefully sane value */
701 ctrl->value64 = 0;
702 ctrl->value = val;
703 }
704 break;
705 }
706
707 case VIDIOC_S_EXT_CTRLS:
708 {
709 struct v4l2_ext_controls *ctls =
710 (struct v4l2_ext_controls *)arg;
711 struct v4l2_ext_control *ctrl;
712 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300713 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300714 for (idx = 0; idx < ctls->count; idx++) {
715 ctrl = ctls->controls + idx;
716 ret = pvr2_ctrl_set_value(
717 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
718 ctrl->value);
719 if (ret) {
720 ctls->error_idx = idx;
721 break;
722 }
723 }
724 break;
725 }
726
727 case VIDIOC_TRY_EXT_CTRLS:
728 {
729 struct v4l2_ext_controls *ctls =
730 (struct v4l2_ext_controls *)arg;
731 struct v4l2_ext_control *ctrl;
732 struct pvr2_ctrl *pctl;
733 unsigned int idx;
734 /* For the moment just validate that the requested control
735 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300736 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300737 for (idx = 0; idx < ctls->count; idx++) {
738 ctrl = ctls->controls + idx;
739 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
740 if (!pctl) {
741 ret = -EINVAL;
742 ctls->error_idx = idx;
743 break;
744 }
745 }
746 break;
747 }
748
Mike Isely432907f2008-08-31 21:02:20 -0300749 case VIDIOC_CROPCAP:
750 {
751 struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
752 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
753 ret = -EINVAL;
754 break;
755 }
756 ret = pvr2_hdw_get_cropcap(hdw, cap);
757 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
758 break;
759 }
760 case VIDIOC_G_CROP:
761 {
762 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
763 int val = 0;
764 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
765 ret = -EINVAL;
766 break;
767 }
768 ret = pvr2_ctrl_get_value(
769 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
770 if (ret != 0) {
771 ret = -EINVAL;
772 break;
773 }
774 crop->c.left = val;
775 ret = pvr2_ctrl_get_value(
776 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
777 if (ret != 0) {
778 ret = -EINVAL;
779 break;
780 }
781 crop->c.top = val;
782 ret = pvr2_ctrl_get_value(
783 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
784 if (ret != 0) {
785 ret = -EINVAL;
786 break;
787 }
788 crop->c.width = val;
789 ret = pvr2_ctrl_get_value(
790 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
791 if (ret != 0) {
792 ret = -EINVAL;
793 break;
794 }
795 crop->c.height = val;
796 }
797 case VIDIOC_S_CROP:
798 {
799 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
Mike Isely432907f2008-08-31 21:02:20 -0300800 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
801 ret = -EINVAL;
802 break;
803 }
Mike Isely432907f2008-08-31 21:02:20 -0300804 ret = pvr2_ctrl_set_value(
805 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
806 crop->c.left);
807 if (ret != 0) {
808 ret = -EINVAL;
809 break;
810 }
811 ret = pvr2_ctrl_set_value(
812 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
813 crop->c.top);
814 if (ret != 0) {
815 ret = -EINVAL;
816 break;
817 }
818 ret = pvr2_ctrl_set_value(
819 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
820 crop->c.width);
821 if (ret != 0) {
822 ret = -EINVAL;
823 break;
824 }
825 ret = pvr2_ctrl_set_value(
826 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
827 crop->c.height);
828 if (ret != 0) {
829 ret = -EINVAL;
830 break;
831 }
832 }
Mike Iselyd8554972006-06-26 20:58:46 -0300833 case VIDIOC_LOG_STATUS:
834 {
Mike Iselyd8554972006-06-26 20:58:46 -0300835 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300836 ret = 0;
837 break;
838 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300839#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300840 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300841 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300842 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300843 u64 val;
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300844 struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300845 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300846 ret = pvr2_hdw_register_access(
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300847 hdw, &req->match, req->reg,
848 cmd == VIDIOC_DBG_S_REGISTER, &val);
Trent Piepho52ebc762007-01-23 22:38:13 -0300849 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300850 break;
851 }
852#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300853
854 default :
Mauro Carvalho Chehab7a286cc2011-06-26 10:18:03 -0300855 ret = -ENOTTY;
Hans Verkuil08af2452010-12-24 10:33:19 -0300856 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300857 }
858
859 pvr2_hdw_commit_ctl(hdw);
860
861 if (ret < 0) {
862 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300863 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300864 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300865 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300866 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
867 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300868 "pvr2_v4l2_do_ioctl failure, ret=%ld"
869 " command was:", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300870 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
871 cmd);
872 }
873 }
874 } else {
875 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300876 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
877 ret, ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300878 }
879 return ret;
880}
881
Mike Iselyd8554972006-06-26 20:58:46 -0300882static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
883{
Mike Isely0f0f2572006-12-27 23:19:42 -0300884 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300885 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300886 char msg[80];
887 unsigned int mcnt;
888
889 /* Construct the unregistration message *before* we actually
890 perform the unregistration step. By doing it this way we don't
891 have to worry about potentially touching deleted resources. */
892 mcnt = scnprintf(msg, sizeof(msg) - 1,
893 "pvrusb2: unregistered device %s [%s]",
894 video_device_node_name(&dip->devbase),
895 pvr2_config_get_name(cfg));
896 msg[mcnt] = 0;
Mike Isely0f0f2572006-12-27 23:19:42 -0300897
Mike Isely16eb40d2006-12-30 18:27:32 -0300898 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300899
900 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300901 dip->v4lp = NULL;
902 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300903
904 /* Actual deallocation happens later when all internal references
905 are gone. */
906 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300907
Mike Iselyd72baad2010-05-15 00:15:38 -0300908 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f2572006-12-27 23:19:42 -0300909
Mike Iselyd8554972006-06-26 20:58:46 -0300910}
911
912
Mike Isely4a89baa2009-10-12 00:13:28 -0300913static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
914{
915 if (!dip) return;
916 if (!dip->devbase.parent) return;
917 dip->devbase.parent = NULL;
918 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
919}
920
921
Mike Iselyd8554972006-06-26 20:58:46 -0300922static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
923{
Mike Isely0f0f2572006-12-27 23:19:42 -0300924 if (vp->dev_video) {
925 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000926 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300927 }
928 if (vp->dev_radio) {
929 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000930 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300931 }
Mike Iselyd8554972006-06-26 20:58:46 -0300932
933 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
934 pvr2_channel_done(&vp->channel);
935 kfree(vp);
936}
937
938
Mike Isely75910052006-09-23 22:30:50 -0300939static void pvr2_video_device_release(struct video_device *vdev)
940{
941 struct pvr2_v4l2_dev *dev;
942 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
943 kfree(dev);
944}
945
946
Adrian Bunk07e337e2006-06-30 11:30:20 -0300947static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300948{
949 struct pvr2_v4l2 *vp;
950 vp = container_of(chp,struct pvr2_v4l2,channel);
951 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300952 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
953 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300954 if (vp->vfirst) return;
955 pvr2_v4l2_destroy_no_lock(vp);
956}
957
958
Hans Verkuil069b7472008-12-30 07:04:34 -0300959static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300960 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300961{
962
Hans Verkuilf473bf72008-11-01 08:25:11 -0300963 return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
Mike Iselyd8554972006-06-26 20:58:46 -0300964}
965
966
Hans Verkuilbec43662008-12-30 06:58:20 -0300967static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300968{
969 struct pvr2_v4l2_fh *fhp = file->private_data;
970 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300971 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300972
973 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
974
975 if (fhp->rhp) {
976 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300977 pvr2_hdw_set_streaming(hdw,0);
978 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300979 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300980 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300981 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300982 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300983
Hans Verkuilffb48772010-05-01 08:03:24 -0300984 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300985 file->private_data = NULL;
986
Mike Isely794b1602008-04-22 14:45:45 -0300987 if (fhp->vnext) {
988 fhp->vnext->vprev = fhp->vprev;
989 } else {
990 vp->vlast = fhp->vprev;
991 }
992 if (fhp->vprev) {
993 fhp->vprev->vnext = fhp->vnext;
994 } else {
995 vp->vfirst = fhp->vnext;
996 }
997 fhp->vnext = NULL;
998 fhp->vprev = NULL;
999 fhp->vhead = NULL;
1000 pvr2_channel_done(&fhp->channel);
1001 pvr2_trace(PVR2_TRACE_STRUCT,
1002 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001003 if (fhp->input_map) {
1004 kfree(fhp->input_map);
1005 fhp->input_map = NULL;
1006 }
Mike Isely794b1602008-04-22 14:45:45 -03001007 kfree(fhp);
1008 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1009 pvr2_v4l2_destroy_no_lock(vp);
1010 }
Mike Iselyd8554972006-06-26 20:58:46 -03001011 return 0;
1012}
1013
1014
Hans Verkuilbec43662008-12-30 06:58:20 -03001015static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001016{
Mike Isely75910052006-09-23 22:30:50 -03001017 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001018 struct pvr2_v4l2_fh *fhp;
1019 struct pvr2_v4l2 *vp;
1020 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001021 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001022 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001023 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001024
Mike Isely75910052006-09-23 22:30:50 -03001025 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001026
1027 vp = dip->v4lp;
1028 hdw = vp->channel.hdw;
1029
1030 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1031
1032 if (!pvr2_hdw_dev_ok(hdw)) {
1033 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1034 "pvr2_v4l2_open: hardware not ready");
1035 return -EIO;
1036 }
1037
Mike Isely4b85dee2007-01-20 00:03:32 -03001038 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001039 if (!fhp) {
1040 return -ENOMEM;
1041 }
Mike Iselyd8554972006-06-26 20:58:46 -03001042
1043 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001044 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001045
Mike Isely794b1602008-04-22 14:45:45 -03001046 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1047 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001048
Mike Isely1cb03b72008-04-21 03:47:43 -03001049 if (dip->v4l_type == VFL_TYPE_RADIO) {
1050 /* Opening device as a radio, legal input selection subset
1051 is just the radio. */
1052 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1053 } else {
1054 /* Opening the main V4L device, legal input selection
1055 subset includes all analog inputs. */
1056 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1057 (1 << PVR2_CVAL_INPUT_TV) |
1058 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1059 (1 << PVR2_CVAL_INPUT_SVIDEO));
1060 }
1061 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1062 if (ret) {
1063 pvr2_channel_done(&fhp->channel);
1064 pvr2_trace(PVR2_TRACE_STRUCT,
1065 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1066 fhp);
1067
1068 kfree(fhp);
1069 return ret;
1070 }
1071
Mike Iselye57b1c82008-04-21 03:52:34 -03001072 input_mask &= pvr2_hdw_get_input_available(hdw);
1073 input_cnt = 0;
1074 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1075 if (input_mask & (1 << idx)) input_cnt++;
1076 }
1077 fhp->input_cnt = input_cnt;
1078 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1079 if (!fhp->input_map) {
1080 pvr2_channel_done(&fhp->channel);
1081 pvr2_trace(PVR2_TRACE_STRUCT,
1082 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1083 fhp);
1084 kfree(fhp);
1085 return -ENOMEM;
1086 }
1087 input_cnt = 0;
1088 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1089 if (!(input_mask & (1 << idx))) continue;
1090 fhp->input_map[input_cnt++] = idx;
1091 }
1092
Mike Isely794b1602008-04-22 14:45:45 -03001093 fhp->vnext = NULL;
1094 fhp->vprev = vp->vlast;
1095 if (vp->vlast) {
1096 vp->vlast->vnext = fhp;
1097 } else {
1098 vp->vfirst = fhp;
1099 }
1100 vp->vlast = fhp;
1101 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001102
Mike Iselyd8554972006-06-26 20:58:46 -03001103 fhp->file = file;
1104 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001105 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001106
1107 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1108
1109 return 0;
1110}
1111
1112
1113static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1114{
1115 wake_up(&fhp->wait_data);
1116}
1117
1118static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1119{
1120 int ret;
1121 struct pvr2_stream *sp;
1122 struct pvr2_hdw *hdw;
1123 if (fh->rhp) return 0;
1124
Joe Perches108bdd72010-04-05 16:05:39 -03001125 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001126 /* No stream defined for this node. This means that we're
1127 not currently allowed to stream from this node. */
1128 return -EPERM;
1129 }
1130
Mike Iselyd8554972006-06-26 20:58:46 -03001131 /* First read() attempt. Try to claim the stream and start
1132 it... */
1133 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001134 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001135 /* Someone else must already have it */
1136 return ret;
1137 }
1138
Joe Perches108bdd72010-04-05 16:05:39 -03001139 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001140 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001141 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001142 return -ENOMEM;
1143 }
1144
1145 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001146 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001147 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001148 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001149 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1150 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001151}
1152
1153
1154static ssize_t pvr2_v4l2_read(struct file *file,
1155 char __user *buff, size_t count, loff_t *ppos)
1156{
1157 struct pvr2_v4l2_fh *fh = file->private_data;
1158 int ret;
1159
1160 if (fh->fw_mode_flag) {
1161 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1162 char *tbuf;
1163 int c1,c2;
1164 int tcnt = 0;
1165 unsigned int offs = *ppos;
1166
1167 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1168 if (!tbuf) return -ENOMEM;
1169
1170 while (count) {
1171 c1 = count;
1172 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1173 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1174 if (c2 < 0) {
1175 tcnt = c2;
1176 break;
1177 }
1178 if (!c2) break;
1179 if (copy_to_user(buff,tbuf,c2)) {
1180 tcnt = -EFAULT;
1181 break;
1182 }
1183 offs += c2;
1184 tcnt += c2;
1185 buff += c2;
1186 count -= c2;
1187 *ppos += c2;
1188 }
1189 kfree(tbuf);
1190 return tcnt;
1191 }
1192
1193 if (!fh->rhp) {
1194 ret = pvr2_v4l2_iosetup(fh);
1195 if (ret) {
1196 return ret;
1197 }
1198 }
1199
1200 for (;;) {
1201 ret = pvr2_ioread_read(fh->rhp,buff,count);
1202 if (ret >= 0) break;
1203 if (ret != -EAGAIN) break;
1204 if (file->f_flags & O_NONBLOCK) break;
1205 /* Doing blocking I/O. Wait here. */
1206 ret = wait_event_interruptible(
1207 fh->wait_data,
1208 pvr2_ioread_avail(fh->rhp) >= 0);
1209 if (ret < 0) break;
1210 }
1211
1212 return ret;
1213}
1214
1215
1216static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1217{
1218 unsigned int mask = 0;
1219 struct pvr2_v4l2_fh *fh = file->private_data;
1220 int ret;
1221
1222 if (fh->fw_mode_flag) {
1223 mask |= POLLIN | POLLRDNORM;
1224 return mask;
1225 }
1226
1227 if (!fh->rhp) {
1228 ret = pvr2_v4l2_iosetup(fh);
1229 if (ret) return POLLERR;
1230 }
1231
1232 poll_wait(file,&fh->wait_data,wait);
1233
1234 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1235 mask |= POLLIN | POLLRDNORM;
1236 }
1237
1238 return mask;
1239}
1240
1241
Hans Verkuilbec43662008-12-30 06:58:20 -03001242static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001243 .owner = THIS_MODULE,
1244 .open = pvr2_v4l2_open,
1245 .release = pvr2_v4l2_release,
1246 .read = pvr2_v4l2_read,
1247 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001248 .poll = pvr2_v4l2_poll,
1249};
1250
1251
Mike Iselyd8554972006-06-26 20:58:46 -03001252static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001253 .fops = &vdev_fops,
1254};
1255
1256
1257static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1258 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001259 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001260{
Mike Isely4a89baa2009-10-12 00:13:28 -03001261 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001262 int mindevnum;
1263 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001264 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001265 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001266
Mike Isely4a89baa2009-10-12 00:13:28 -03001267 usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001268 dip->v4l_type = v4l_type;
1269 switch (v4l_type) {
1270 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001271 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001272 dip->config = pvr2_config_mpeg;
1273 dip->minor_type = pvr2_v4l_type_video;
1274 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001275 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001276 pr_err(KBUILD_MODNAME
1277 ": Failed to set up pvrusb2 v4l video dev"
1278 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001279 return;
1280 }
Mike Iselyd8554972006-06-26 20:58:46 -03001281 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001282 case VFL_TYPE_VBI:
1283 dip->config = pvr2_config_vbi;
1284 dip->minor_type = pvr2_v4l_type_vbi;
1285 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001286 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001287 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001288 dip->stream = &vp->channel.mc_head->video_stream;
1289 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001290 dip->minor_type = pvr2_v4l_type_radio;
1291 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001292 break;
1293 default:
1294 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001295 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1296 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001297 return;
1298 }
1299
Mike Isely75910052006-09-23 22:30:50 -03001300 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1301 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001302
1303 mindevnum = -1;
1304 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001305 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1306 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001307 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001308 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001309 if ((video_register_device(&dip->devbase,
1310 dip->v4l_type, mindevnum) < 0) &&
1311 (video_register_device(&dip->devbase,
1312 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001313 pr_err(KBUILD_MODNAME
1314 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001315 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001316
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001317 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1318 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001319 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001320
Mike Iselyd8554972006-06-26 20:58:46 -03001321 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001322 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001323}
1324
1325
1326struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1327{
1328 struct pvr2_v4l2 *vp;
1329
Mike Isely4b85dee2007-01-20 00:03:32 -03001330 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001331 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001332 pvr2_channel_init(&vp->channel,mnp);
1333 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1334
1335 vp->channel.check_func = pvr2_v4l2_internal_check;
1336
1337 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001338 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1339 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001340 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001341 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1342 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001343 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1344 if (!vp->dev_radio) goto fail;
1345 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1346 }
Mike Iselyd8554972006-06-26 20:58:46 -03001347
1348 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001349 fail:
1350 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1351 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001352 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001353}
1354
1355/*
1356 Stuff for Emacs to see, in order to encourage consistent editing style:
1357 *** Local Variables: ***
1358 *** mode: c ***
1359 *** fill-column: 75 ***
1360 *** tab-width: 8 ***
1361 *** c-basic-offset: 8 ***
1362 *** End: ***
1363 */