blob: 5ffa0d2b0b0d957c9b94d118110078f4daf9eb22 [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",
Mike Isely48c5b0d2009-05-02 00:04:35 -030094 .version = KERNEL_VERSION(0, 9, 0),
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
230 case VIDIOC_G_STD:
231 {
232 int val = 0;
233 ret = pvr2_ctrl_get_value(
234 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
235 *(v4l2_std_id *)arg = val;
236 break;
237 }
238
239 case VIDIOC_S_STD:
240 {
241 ret = pvr2_ctrl_set_value(
242 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
243 *(v4l2_std_id *)arg);
244 break;
245 }
246
247 case VIDIOC_ENUMINPUT:
248 {
249 struct pvr2_ctrl *cptr;
250 struct v4l2_input *vi = (struct v4l2_input *)arg;
251 struct v4l2_input tmp;
252 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300253 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300254
255 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
256
257 memset(&tmp,0,sizeof(tmp));
258 tmp.index = vi->index;
259 ret = 0;
Roel Kluin223ffe52009-05-02 16:38:47 -0300260 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300261 ret = -EINVAL;
262 break;
263 }
Mike Iselye57b1c82008-04-21 03:52:34 -0300264 val = fh->input_map[vi->index];
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300265 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300266 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300267 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300268 case PVR2_CVAL_INPUT_RADIO:
269 tmp.type = V4L2_INPUT_TYPE_TUNER;
270 break;
271 case PVR2_CVAL_INPUT_SVIDEO:
272 case PVR2_CVAL_INPUT_COMPOSITE:
273 tmp.type = V4L2_INPUT_TYPE_CAMERA;
274 break;
275 default:
276 ret = -EINVAL;
277 break;
278 }
279 if (ret < 0) break;
280
281 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300282 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300283 tmp.name,sizeof(tmp.name)-1,&cnt);
284 tmp.name[cnt] = 0;
285
286 /* Don't bother with audioset, since this driver currently
287 always switches the audio whenever the video is
288 switched. */
289
290 /* Handling std is a tougher problem. It doesn't make
291 sense in cases where a device might be multi-standard.
292 We could just copy out the current value for the
293 standard, but it can change over time. For now just
294 leave it zero. */
295
296 memcpy(vi, &tmp, sizeof(tmp));
297
298 ret = 0;
299 break;
300 }
301
302 case VIDIOC_G_INPUT:
303 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300304 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300305 struct pvr2_ctrl *cptr;
306 struct v4l2_input *vi = (struct v4l2_input *)arg;
307 int val;
308 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
309 val = 0;
310 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300311 vi->index = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300312 for (idx = 0; idx < fh->input_cnt; idx++) {
313 if (fh->input_map[idx] == val) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300314 vi->index = idx;
315 break;
316 }
317 }
Mike Iselyd8554972006-06-26 20:58:46 -0300318 break;
319 }
320
321 case VIDIOC_S_INPUT:
322 {
323 struct v4l2_input *vi = (struct v4l2_input *)arg;
Roel Kluin223ffe52009-05-02 16:38:47 -0300324 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300325 ret = -ERANGE;
326 break;
327 }
Mike Iselyd8554972006-06-26 20:58:46 -0300328 ret = pvr2_ctrl_set_value(
329 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselye57b1c82008-04-21 03:52:34 -0300330 fh->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300331 break;
332 }
333
334 case VIDIOC_ENUMAUDIO:
335 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300336 /* pkt: FIXME: We are returning one "fake" input here
337 which could very well be called "whatever_we_like".
338 This is for apps that want to see an audio input
339 just to feel comfortable, as well as to test if
340 it can do stereo or sth. There is actually no guarantee
341 that the actual audio input cannot change behind the app's
342 back, but most applications should not mind that either.
343
344 Hopefully, mplayer people will work with us on this (this
345 whole mess is to support mplayer pvr://), or Hans will come
346 up with a more standard way to say "we have inputs but we
347 don 't want you to change them independent of video" which
348 will sort this mess.
349 */
350 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300351 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300352 if (vin->index > 0) break;
353 strncpy(vin->name, "PVRUSB2 Audio",14);
354 vin->capability = V4L2_AUDCAP_STEREO;
355 ret = 0;
356 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300357 break;
358 }
359
360 case VIDIOC_G_AUDIO:
361 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300362 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
363 struct v4l2_audio *vin = arg;
364 memset(vin,0,sizeof(*vin));
365 vin->index = 0;
366 strncpy(vin->name, "PVRUSB2 Audio",14);
367 vin->capability = V4L2_AUDCAP_STEREO;
368 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300369 break;
370 }
371
372 case VIDIOC_S_AUDIO:
373 {
374 ret = -EINVAL;
375 break;
376 }
377 case VIDIOC_G_TUNER:
378 {
379 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300380
Michael Krufky8d364362007-01-22 02:17:55 -0300381 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300382
Mike Isely18103c572007-01-20 00:09:47 -0300383 pvr2_hdw_execute_tuner_poll(hdw);
384 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300385 break;
386 }
387
388 case VIDIOC_S_TUNER:
389 {
390 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
391
392 if (vt->index != 0)
393 break;
394
395 ret = pvr2_ctrl_set_value(
396 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
397 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300398 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300399 }
400
401 case VIDIOC_S_FREQUENCY:
402 {
403 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300404 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300405 struct v4l2_tuner vt;
406 int cur_input;
407 struct pvr2_ctrl *ctrlp;
408 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
409 if (ret != 0) break;
410 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
411 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
412 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300413 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300414 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
415 pvr2_ctrl_set_value(ctrlp,
416 PVR2_CVAL_INPUT_RADIO);
417 }
418 } else {
419 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
420 pvr2_ctrl_set_value(ctrlp,
421 PVR2_CVAL_INPUT_TV);
422 }
423 }
424 fv = vf->frequency;
425 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300426 fv = (fv * 125) / 2;
427 } else {
428 fv = fv * 62500;
429 }
Mike Iselyd8554972006-06-26 20:58:46 -0300430 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300431 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300432 break;
433 }
434
435 case VIDIOC_G_FREQUENCY:
436 {
437 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
438 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300439 int cur_input;
440 struct v4l2_tuner vt;
441 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
442 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300443 ret = pvr2_ctrl_get_value(
444 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
445 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300446 if (ret != 0) break;
447 pvr2_ctrl_get_value(
448 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
449 &cur_input);
450 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300451 vf->type = V4L2_TUNER_RADIO;
452 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300453 vf->type = V4L2_TUNER_ANALOG_TV;
454 }
Mike Isely18103c572007-01-20 00:09:47 -0300455 if (vt.capability & V4L2_TUNER_CAP_LOW) {
456 val = (val * 2) / 125;
457 } else {
458 val /= 62500;
459 }
460 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300461 break;
462 }
463
464 case VIDIOC_ENUM_FMT:
465 {
466 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
467
468 /* Only one format is supported : mpeg.*/
469 if (fd->index != 0)
470 break;
471
472 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
473 ret = 0;
474 break;
475 }
476
477 case VIDIOC_G_FMT:
478 {
479 struct v4l2_format *vf = (struct v4l2_format *)arg;
480 int val;
481 switch(vf->type) {
482 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
483 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
484 sizeof(struct v4l2_format));
485 val = 0;
486 pvr2_ctrl_get_value(
487 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
488 &val);
489 vf->fmt.pix.width = val;
490 val = 0;
491 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300492 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
493 &val);
494 vf->fmt.pix.height = val;
495 ret = 0;
496 break;
497 case V4L2_BUF_TYPE_VBI_CAPTURE:
498 // ????? Still need to figure out to do VBI correctly
499 ret = -EINVAL;
500 break;
501 default:
502 ret = -EINVAL;
503 break;
504 }
505 break;
506 }
507
508 case VIDIOC_TRY_FMT:
509 case VIDIOC_S_FMT:
510 {
511 struct v4l2_format *vf = (struct v4l2_format *)arg;
512
513 ret = 0;
514 switch(vf->type) {
515 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300516 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300517 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300518 int h = vf->fmt.pix.height;
519 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300520 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
521 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300522
Mike Iselye95a1912006-08-08 09:10:07 -0300523 lmin = pvr2_ctrl_get_min(hcp);
524 lmax = pvr2_ctrl_get_max(hcp);
Mike Isely26dd1c572008-08-31 20:55:03 -0300525 pvr2_ctrl_get_def(hcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300526 if (w == -1) {
527 w = ldef;
528 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300529 w = lmin;
530 } else if (w > lmax) {
531 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300532 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300533 lmin = pvr2_ctrl_get_min(vcp);
534 lmax = pvr2_ctrl_get_max(vcp);
Mike Isely26dd1c572008-08-31 20:55:03 -0300535 pvr2_ctrl_get_def(vcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300536 if (h == -1) {
537 h = ldef;
538 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300539 h = lmin;
540 } else if (h > lmax) {
541 h = lmax;
542 }
Mike Iselyd8554972006-06-26 20:58:46 -0300543
544 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
545 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300546 vf->fmt.pix.width = w;
547 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300548
549 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300550 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
551 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300552 }
553 } break;
554 case V4L2_BUF_TYPE_VBI_CAPTURE:
555 // ????? Still need to figure out to do VBI correctly
556 ret = -EINVAL;
557 break;
558 default:
559 ret = -EINVAL;
560 break;
561 }
562 break;
563 }
564
565 case VIDIOC_STREAMON:
566 {
Joe Perches108bdd72010-04-05 16:05:39 -0300567 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300568 /* No stream defined for this node. This means
569 that we're not currently allowed to stream from
570 this node. */
571 ret = -EPERM;
572 break;
573 }
Joe Perches108bdd72010-04-05 16:05:39 -0300574 ret = pvr2_hdw_set_stream_type(hdw,pdi->config);
Mike Iselyd8554972006-06-26 20:58:46 -0300575 if (ret < 0) return ret;
576 ret = pvr2_hdw_set_streaming(hdw,!0);
577 break;
578 }
579
580 case VIDIOC_STREAMOFF:
581 {
Joe Perches108bdd72010-04-05 16:05:39 -0300582 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300583 /* No stream defined for this node. This means
584 that we're not currently allowed to stream from
585 this node. */
586 ret = -EPERM;
587 break;
588 }
Mike Iselyd8554972006-06-26 20:58:46 -0300589 ret = pvr2_hdw_set_streaming(hdw,0);
590 break;
591 }
592
593 case VIDIOC_QUERYCTRL:
594 {
595 struct pvr2_ctrl *cptr;
Mike Isely26dd1c572008-08-31 20:55:03 -0300596 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300597 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
598 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300599 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
600 cptr = pvr2_hdw_get_ctrl_nextv4l(
601 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
602 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
603 } else {
604 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
605 }
Mike Iselyd8554972006-06-26 20:58:46 -0300606 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300607 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300608 "QUERYCTRL id=0x%x not implemented here",
609 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300610 ret = -EINVAL;
611 break;
612 }
613
Mike Iselya761f432006-06-25 20:04:44 -0300614 pvr2_trace(PVR2_TRACE_V4LIOCTL,
615 "QUERYCTRL id=0x%x mapping name=%s (%s)",
616 vc->id,pvr2_ctrl_get_name(cptr),
617 pvr2_ctrl_get_desc(cptr));
618 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
619 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Isely26dd1c572008-08-31 20:55:03 -0300620 pvr2_ctrl_get_def(cptr, &val);
621 vc->default_value = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300622 switch (pvr2_ctrl_get_type(cptr)) {
623 case pvr2_ctl_enum:
624 vc->type = V4L2_CTRL_TYPE_MENU;
625 vc->minimum = 0;
626 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
627 vc->step = 1;
628 break;
Mike Isely33213962006-06-25 20:04:40 -0300629 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300630 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300631 vc->minimum = 0;
632 vc->maximum = 1;
633 vc->step = 1;
634 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300635 case pvr2_ctl_int:
636 vc->type = V4L2_CTRL_TYPE_INTEGER;
637 vc->minimum = pvr2_ctrl_get_min(cptr);
638 vc->maximum = pvr2_ctrl_get_max(cptr);
639 vc->step = 1;
640 break;
641 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300642 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300643 "QUERYCTRL id=0x%x name=%s not mappable",
644 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300645 ret = -EINVAL;
646 break;
647 }
648 break;
649 }
650
651 case VIDIOC_QUERYMENU:
652 {
653 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
654 unsigned int cnt = 0;
655 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
656 vm->index,
657 vm->name,sizeof(vm->name)-1,
658 &cnt);
659 vm->name[cnt] = 0;
660 break;
661 }
662
663 case VIDIOC_G_CTRL:
664 {
665 struct v4l2_control *vc = (struct v4l2_control *)arg;
666 int val = 0;
667 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
668 &val);
669 vc->value = val;
670 break;
671 }
672
673 case VIDIOC_S_CTRL:
674 {
675 struct v4l2_control *vc = (struct v4l2_control *)arg;
676 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
677 vc->value);
678 break;
679 }
680
Mike Isely1d9f8462006-06-25 20:04:58 -0300681 case VIDIOC_G_EXT_CTRLS:
682 {
683 struct v4l2_ext_controls *ctls =
684 (struct v4l2_ext_controls *)arg;
685 struct v4l2_ext_control *ctrl;
686 unsigned int idx;
687 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300688 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300689 for (idx = 0; idx < ctls->count; idx++) {
690 ctrl = ctls->controls + idx;
691 ret = pvr2_ctrl_get_value(
692 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
693 if (ret) {
694 ctls->error_idx = idx;
695 break;
696 }
697 /* Ensure that if read as a 64 bit value, the user
698 will still get a hopefully sane value */
699 ctrl->value64 = 0;
700 ctrl->value = val;
701 }
702 break;
703 }
704
705 case VIDIOC_S_EXT_CTRLS:
706 {
707 struct v4l2_ext_controls *ctls =
708 (struct v4l2_ext_controls *)arg;
709 struct v4l2_ext_control *ctrl;
710 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300711 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300712 for (idx = 0; idx < ctls->count; idx++) {
713 ctrl = ctls->controls + idx;
714 ret = pvr2_ctrl_set_value(
715 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
716 ctrl->value);
717 if (ret) {
718 ctls->error_idx = idx;
719 break;
720 }
721 }
722 break;
723 }
724
725 case VIDIOC_TRY_EXT_CTRLS:
726 {
727 struct v4l2_ext_controls *ctls =
728 (struct v4l2_ext_controls *)arg;
729 struct v4l2_ext_control *ctrl;
730 struct pvr2_ctrl *pctl;
731 unsigned int idx;
732 /* For the moment just validate that the requested control
733 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300734 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300735 for (idx = 0; idx < ctls->count; idx++) {
736 ctrl = ctls->controls + idx;
737 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
738 if (!pctl) {
739 ret = -EINVAL;
740 ctls->error_idx = idx;
741 break;
742 }
743 }
744 break;
745 }
746
Mike Isely432907f2008-08-31 21:02:20 -0300747 case VIDIOC_CROPCAP:
748 {
749 struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
750 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
751 ret = -EINVAL;
752 break;
753 }
754 ret = pvr2_hdw_get_cropcap(hdw, cap);
755 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
756 break;
757 }
758 case VIDIOC_G_CROP:
759 {
760 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
761 int val = 0;
762 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
763 ret = -EINVAL;
764 break;
765 }
766 ret = pvr2_ctrl_get_value(
767 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
768 if (ret != 0) {
769 ret = -EINVAL;
770 break;
771 }
772 crop->c.left = val;
773 ret = pvr2_ctrl_get_value(
774 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
775 if (ret != 0) {
776 ret = -EINVAL;
777 break;
778 }
779 crop->c.top = val;
780 ret = pvr2_ctrl_get_value(
781 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
782 if (ret != 0) {
783 ret = -EINVAL;
784 break;
785 }
786 crop->c.width = val;
787 ret = pvr2_ctrl_get_value(
788 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
789 if (ret != 0) {
790 ret = -EINVAL;
791 break;
792 }
793 crop->c.height = val;
794 }
795 case VIDIOC_S_CROP:
796 {
797 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
798 struct v4l2_cropcap cap;
799 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
800 ret = -EINVAL;
801 break;
802 }
803 cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
804 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 Verkuilaecde8b52008-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 Verkuilaecde8b52008-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 Chehabb1f88402008-10-21 11:27:20 -0300855 ret = v4l_compat_translate_ioctl(file, cmd,
Hans Verkuilf473bf72008-11-01 08:25:11 -0300856 arg, pvr2_v4l2_do_ioctl);
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 Isely0f0f2572006-12-27 23:19:42 -0300886
Mike Isely16eb40d2006-12-30 18:27:32 -0300887 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300888
889 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300890 dip->v4lp = NULL;
891 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300892
893 /* Actual deallocation happens later when all internal references
894 are gone. */
895 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300896
Laurent Pinchart38c7c032009-11-27 13:57:15 -0300897 printk(KERN_INFO "pvrusb2: unregistered device %s [%s]\n",
898 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -0300899 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300900
Mike Iselyd8554972006-06-26 20:58:46 -0300901}
902
903
Mike Isely4a89baa2009-10-12 00:13:28 -0300904static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
905{
906 if (!dip) return;
907 if (!dip->devbase.parent) return;
908 dip->devbase.parent = NULL;
909 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
910}
911
912
Mike Iselyd8554972006-06-26 20:58:46 -0300913static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
914{
Mike Isely0f0f2572006-12-27 23:19:42 -0300915 if (vp->dev_video) {
916 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000917 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300918 }
919 if (vp->dev_radio) {
920 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000921 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300922 }
Mike Iselyd8554972006-06-26 20:58:46 -0300923
924 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
925 pvr2_channel_done(&vp->channel);
926 kfree(vp);
927}
928
929
Mike Isely75910052006-09-23 22:30:50 -0300930static void pvr2_video_device_release(struct video_device *vdev)
931{
932 struct pvr2_v4l2_dev *dev;
933 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
934 kfree(dev);
935}
936
937
Adrian Bunk07e337e2006-06-30 11:30:20 -0300938static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300939{
940 struct pvr2_v4l2 *vp;
941 vp = container_of(chp,struct pvr2_v4l2,channel);
942 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300943 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
944 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300945 if (vp->vfirst) return;
946 pvr2_v4l2_destroy_no_lock(vp);
947}
948
949
Hans Verkuil069b7472008-12-30 07:04:34 -0300950static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300951 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300952{
953
Hans Verkuilf473bf72008-11-01 08:25:11 -0300954 return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
Mike Iselyd8554972006-06-26 20:58:46 -0300955}
956
957
Hans Verkuilbec43662008-12-30 06:58:20 -0300958static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300959{
960 struct pvr2_v4l2_fh *fhp = file->private_data;
961 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300962 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300963
964 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
965
966 if (fhp->rhp) {
967 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300968 pvr2_hdw_set_streaming(hdw,0);
969 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300970 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300971 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300972 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300973 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300974
Hans Verkuilffb48772010-05-01 08:03:24 -0300975 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300976 file->private_data = NULL;
977
Mike Isely794b1602008-04-22 14:45:45 -0300978 if (fhp->vnext) {
979 fhp->vnext->vprev = fhp->vprev;
980 } else {
981 vp->vlast = fhp->vprev;
982 }
983 if (fhp->vprev) {
984 fhp->vprev->vnext = fhp->vnext;
985 } else {
986 vp->vfirst = fhp->vnext;
987 }
988 fhp->vnext = NULL;
989 fhp->vprev = NULL;
990 fhp->vhead = NULL;
991 pvr2_channel_done(&fhp->channel);
992 pvr2_trace(PVR2_TRACE_STRUCT,
993 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -0300994 if (fhp->input_map) {
995 kfree(fhp->input_map);
996 fhp->input_map = NULL;
997 }
Mike Isely794b1602008-04-22 14:45:45 -0300998 kfree(fhp);
999 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1000 pvr2_v4l2_destroy_no_lock(vp);
1001 }
Mike Iselyd8554972006-06-26 20:58:46 -03001002 return 0;
1003}
1004
1005
Hans Verkuilbec43662008-12-30 06:58:20 -03001006static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001007{
Mike Isely75910052006-09-23 22:30:50 -03001008 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001009 struct pvr2_v4l2_fh *fhp;
1010 struct pvr2_v4l2 *vp;
1011 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001012 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001013 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001014 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001015
Mike Isely75910052006-09-23 22:30:50 -03001016 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001017
1018 vp = dip->v4lp;
1019 hdw = vp->channel.hdw;
1020
1021 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1022
1023 if (!pvr2_hdw_dev_ok(hdw)) {
1024 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1025 "pvr2_v4l2_open: hardware not ready");
1026 return -EIO;
1027 }
1028
Mike Isely4b85dee2007-01-20 00:03:32 -03001029 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001030 if (!fhp) {
1031 return -ENOMEM;
1032 }
Mike Iselyd8554972006-06-26 20:58:46 -03001033
1034 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001035 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001036
Mike Isely794b1602008-04-22 14:45:45 -03001037 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1038 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001039
Mike Isely1cb03b72008-04-21 03:47:43 -03001040 if (dip->v4l_type == VFL_TYPE_RADIO) {
1041 /* Opening device as a radio, legal input selection subset
1042 is just the radio. */
1043 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1044 } else {
1045 /* Opening the main V4L device, legal input selection
1046 subset includes all analog inputs. */
1047 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1048 (1 << PVR2_CVAL_INPUT_TV) |
1049 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1050 (1 << PVR2_CVAL_INPUT_SVIDEO));
1051 }
1052 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1053 if (ret) {
1054 pvr2_channel_done(&fhp->channel);
1055 pvr2_trace(PVR2_TRACE_STRUCT,
1056 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1057 fhp);
1058
1059 kfree(fhp);
1060 return ret;
1061 }
1062
Mike Iselye57b1c82008-04-21 03:52:34 -03001063 input_mask &= pvr2_hdw_get_input_available(hdw);
1064 input_cnt = 0;
1065 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1066 if (input_mask & (1 << idx)) input_cnt++;
1067 }
1068 fhp->input_cnt = input_cnt;
1069 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1070 if (!fhp->input_map) {
1071 pvr2_channel_done(&fhp->channel);
1072 pvr2_trace(PVR2_TRACE_STRUCT,
1073 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1074 fhp);
1075 kfree(fhp);
1076 return -ENOMEM;
1077 }
1078 input_cnt = 0;
1079 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1080 if (!(input_mask & (1 << idx))) continue;
1081 fhp->input_map[input_cnt++] = idx;
1082 }
1083
Mike Isely794b1602008-04-22 14:45:45 -03001084 fhp->vnext = NULL;
1085 fhp->vprev = vp->vlast;
1086 if (vp->vlast) {
1087 vp->vlast->vnext = fhp;
1088 } else {
1089 vp->vfirst = fhp;
1090 }
1091 vp->vlast = fhp;
1092 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001093
Mike Iselyd8554972006-06-26 20:58:46 -03001094 fhp->file = file;
1095 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001096 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001097
1098 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1099
1100 return 0;
1101}
1102
1103
1104static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1105{
1106 wake_up(&fhp->wait_data);
1107}
1108
1109static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1110{
1111 int ret;
1112 struct pvr2_stream *sp;
1113 struct pvr2_hdw *hdw;
1114 if (fh->rhp) return 0;
1115
Joe Perches108bdd72010-04-05 16:05:39 -03001116 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001117 /* No stream defined for this node. This means that we're
1118 not currently allowed to stream from this node. */
1119 return -EPERM;
1120 }
1121
Mike Iselyd8554972006-06-26 20:58:46 -03001122 /* First read() attempt. Try to claim the stream and start
1123 it... */
1124 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001125 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001126 /* Someone else must already have it */
1127 return ret;
1128 }
1129
Joe Perches108bdd72010-04-05 16:05:39 -03001130 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001131 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001132 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001133 return -ENOMEM;
1134 }
1135
1136 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001137 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001138 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001139 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001140 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1141 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001142}
1143
1144
1145static ssize_t pvr2_v4l2_read(struct file *file,
1146 char __user *buff, size_t count, loff_t *ppos)
1147{
1148 struct pvr2_v4l2_fh *fh = file->private_data;
1149 int ret;
1150
1151 if (fh->fw_mode_flag) {
1152 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1153 char *tbuf;
1154 int c1,c2;
1155 int tcnt = 0;
1156 unsigned int offs = *ppos;
1157
1158 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1159 if (!tbuf) return -ENOMEM;
1160
1161 while (count) {
1162 c1 = count;
1163 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1164 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1165 if (c2 < 0) {
1166 tcnt = c2;
1167 break;
1168 }
1169 if (!c2) break;
1170 if (copy_to_user(buff,tbuf,c2)) {
1171 tcnt = -EFAULT;
1172 break;
1173 }
1174 offs += c2;
1175 tcnt += c2;
1176 buff += c2;
1177 count -= c2;
1178 *ppos += c2;
1179 }
1180 kfree(tbuf);
1181 return tcnt;
1182 }
1183
1184 if (!fh->rhp) {
1185 ret = pvr2_v4l2_iosetup(fh);
1186 if (ret) {
1187 return ret;
1188 }
1189 }
1190
1191 for (;;) {
1192 ret = pvr2_ioread_read(fh->rhp,buff,count);
1193 if (ret >= 0) break;
1194 if (ret != -EAGAIN) break;
1195 if (file->f_flags & O_NONBLOCK) break;
1196 /* Doing blocking I/O. Wait here. */
1197 ret = wait_event_interruptible(
1198 fh->wait_data,
1199 pvr2_ioread_avail(fh->rhp) >= 0);
1200 if (ret < 0) break;
1201 }
1202
1203 return ret;
1204}
1205
1206
1207static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1208{
1209 unsigned int mask = 0;
1210 struct pvr2_v4l2_fh *fh = file->private_data;
1211 int ret;
1212
1213 if (fh->fw_mode_flag) {
1214 mask |= POLLIN | POLLRDNORM;
1215 return mask;
1216 }
1217
1218 if (!fh->rhp) {
1219 ret = pvr2_v4l2_iosetup(fh);
1220 if (ret) return POLLERR;
1221 }
1222
1223 poll_wait(file,&fh->wait_data,wait);
1224
1225 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1226 mask |= POLLIN | POLLRDNORM;
1227 }
1228
1229 return mask;
1230}
1231
1232
Hans Verkuilbec43662008-12-30 06:58:20 -03001233static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001234 .owner = THIS_MODULE,
1235 .open = pvr2_v4l2_open,
1236 .release = pvr2_v4l2_release,
1237 .read = pvr2_v4l2_read,
1238 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001239 .poll = pvr2_v4l2_poll,
1240};
1241
1242
Mike Iselyd8554972006-06-26 20:58:46 -03001243static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001244 .fops = &vdev_fops,
1245};
1246
1247
1248static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1249 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001250 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001251{
Mike Isely4a89baa2009-10-12 00:13:28 -03001252 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001253 int mindevnum;
1254 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001255 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001256 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001257
Mike Isely4a89baa2009-10-12 00:13:28 -03001258 usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001259 dip->v4l_type = v4l_type;
1260 switch (v4l_type) {
1261 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001262 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001263 dip->config = pvr2_config_mpeg;
1264 dip->minor_type = pvr2_v4l_type_video;
1265 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001266 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001267 pr_err(KBUILD_MODNAME
1268 ": Failed to set up pvrusb2 v4l video dev"
1269 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001270 return;
1271 }
Mike Iselyd8554972006-06-26 20:58:46 -03001272 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001273 case VFL_TYPE_VBI:
1274 dip->config = pvr2_config_vbi;
1275 dip->minor_type = pvr2_v4l_type_vbi;
1276 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001277 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001278 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001279 dip->stream = &vp->channel.mc_head->video_stream;
1280 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001281 dip->minor_type = pvr2_v4l_type_radio;
1282 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001283 break;
1284 default:
1285 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001286 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1287 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001288 return;
1289 }
1290
Mike Isely75910052006-09-23 22:30:50 -03001291 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1292 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001293
1294 mindevnum = -1;
1295 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001296 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1297 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001298 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001299 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001300 if ((video_register_device(&dip->devbase,
1301 dip->v4l_type, mindevnum) < 0) &&
1302 (video_register_device(&dip->devbase,
1303 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001304 pr_err(KBUILD_MODNAME
1305 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001306 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001307
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001308 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1309 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001310 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001311
Mike Iselyd8554972006-06-26 20:58:46 -03001312 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001313 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001314}
1315
1316
1317struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1318{
1319 struct pvr2_v4l2 *vp;
1320
Mike Isely4b85dee2007-01-20 00:03:32 -03001321 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001322 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001323 pvr2_channel_init(&vp->channel,mnp);
1324 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1325
1326 vp->channel.check_func = pvr2_v4l2_internal_check;
1327
1328 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001329 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1330 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001331 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001332 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1333 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001334 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1335 if (!vp->dev_radio) goto fail;
1336 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1337 }
Mike Iselyd8554972006-06-26 20:58:46 -03001338
1339 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001340 fail:
1341 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1342 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001343 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001344}
1345
1346/*
1347 Stuff for Emacs to see, in order to encourage consistent editing style:
1348 *** Local Variables: ***
1349 *** mode: c ***
1350 *** fill-column: 75 ***
1351 *** tab-width: 8 ***
1352 *** c-basic-offset: 8 ***
1353 *** End: ***
1354 */