blob: ce7ac4595276b8a86da9e8a4641f5b1207e31bc6 [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;
Mauro Carvalho Chehaba5abdb62011-10-04 14:16:14 -0300233 *std = V4L2_STD_ALL;
Mauro Carvalho Chehab7383a472011-10-03 12:22:28 -0300234 ret = pvr2_hdw_get_detected_std(hdw, std);
235 break;
236 }
237
Mike Iselyd8554972006-06-26 20:58:46 -0300238 case VIDIOC_G_STD:
239 {
240 int val = 0;
241 ret = pvr2_ctrl_get_value(
242 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
243 *(v4l2_std_id *)arg = val;
244 break;
245 }
246
247 case VIDIOC_S_STD:
248 {
249 ret = pvr2_ctrl_set_value(
250 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
251 *(v4l2_std_id *)arg);
252 break;
253 }
254
255 case VIDIOC_ENUMINPUT:
256 {
257 struct pvr2_ctrl *cptr;
258 struct v4l2_input *vi = (struct v4l2_input *)arg;
259 struct v4l2_input tmp;
260 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300261 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300262
263 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
264
265 memset(&tmp,0,sizeof(tmp));
266 tmp.index = vi->index;
267 ret = 0;
Roel Kluin223ffe52009-05-02 16:38:47 -0300268 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300269 ret = -EINVAL;
270 break;
271 }
Mike Iselye57b1c82008-04-21 03:52:34 -0300272 val = fh->input_map[vi->index];
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300273 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300274 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300275 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300276 case PVR2_CVAL_INPUT_RADIO:
277 tmp.type = V4L2_INPUT_TYPE_TUNER;
278 break;
279 case PVR2_CVAL_INPUT_SVIDEO:
280 case PVR2_CVAL_INPUT_COMPOSITE:
281 tmp.type = V4L2_INPUT_TYPE_CAMERA;
282 break;
283 default:
284 ret = -EINVAL;
285 break;
286 }
287 if (ret < 0) break;
288
289 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300290 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300291 tmp.name,sizeof(tmp.name)-1,&cnt);
292 tmp.name[cnt] = 0;
293
294 /* Don't bother with audioset, since this driver currently
295 always switches the audio whenever the video is
296 switched. */
297
298 /* Handling std is a tougher problem. It doesn't make
299 sense in cases where a device might be multi-standard.
300 We could just copy out the current value for the
301 standard, but it can change over time. For now just
302 leave it zero. */
303
304 memcpy(vi, &tmp, sizeof(tmp));
305
306 ret = 0;
307 break;
308 }
309
310 case VIDIOC_G_INPUT:
311 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300312 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300313 struct pvr2_ctrl *cptr;
314 struct v4l2_input *vi = (struct v4l2_input *)arg;
315 int val;
316 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
317 val = 0;
318 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300319 vi->index = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -0300320 for (idx = 0; idx < fh->input_cnt; idx++) {
321 if (fh->input_map[idx] == val) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300322 vi->index = idx;
323 break;
324 }
325 }
Mike Iselyd8554972006-06-26 20:58:46 -0300326 break;
327 }
328
329 case VIDIOC_S_INPUT:
330 {
331 struct v4l2_input *vi = (struct v4l2_input *)arg;
Roel Kluin223ffe52009-05-02 16:38:47 -0300332 if (vi->index >= fh->input_cnt) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300333 ret = -ERANGE;
334 break;
335 }
Mike Iselyd8554972006-06-26 20:58:46 -0300336 ret = pvr2_ctrl_set_value(
337 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselye57b1c82008-04-21 03:52:34 -0300338 fh->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300339 break;
340 }
341
342 case VIDIOC_ENUMAUDIO:
343 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300344 /* pkt: FIXME: We are returning one "fake" input here
345 which could very well be called "whatever_we_like".
346 This is for apps that want to see an audio input
347 just to feel comfortable, as well as to test if
348 it can do stereo or sth. There is actually no guarantee
349 that the actual audio input cannot change behind the app's
350 back, but most applications should not mind that either.
351
352 Hopefully, mplayer people will work with us on this (this
353 whole mess is to support mplayer pvr://), or Hans will come
354 up with a more standard way to say "we have inputs but we
355 don 't want you to change them independent of video" which
356 will sort this mess.
357 */
358 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300359 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300360 if (vin->index > 0) break;
361 strncpy(vin->name, "PVRUSB2 Audio",14);
362 vin->capability = V4L2_AUDCAP_STEREO;
363 ret = 0;
364 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300365 break;
366 }
367
368 case VIDIOC_G_AUDIO:
369 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300370 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
371 struct v4l2_audio *vin = arg;
372 memset(vin,0,sizeof(*vin));
373 vin->index = 0;
374 strncpy(vin->name, "PVRUSB2 Audio",14);
375 vin->capability = V4L2_AUDCAP_STEREO;
376 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300377 break;
378 }
379
Mike Iselyd8554972006-06-26 20:58:46 -0300380 case VIDIOC_G_TUNER:
381 {
382 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300383
Michael Krufky8d364362007-01-22 02:17:55 -0300384 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300385
Mike Isely18103c52007-01-20 00:09:47 -0300386 pvr2_hdw_execute_tuner_poll(hdw);
387 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300388 break;
389 }
390
391 case VIDIOC_S_TUNER:
392 {
393 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
394
395 if (vt->index != 0)
396 break;
397
398 ret = pvr2_ctrl_set_value(
399 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
400 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300401 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300402 }
403
404 case VIDIOC_S_FREQUENCY:
405 {
406 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300407 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300408 struct v4l2_tuner vt;
409 int cur_input;
410 struct pvr2_ctrl *ctrlp;
411 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
412 if (ret != 0) break;
413 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
414 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
415 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300416 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300417 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
418 pvr2_ctrl_set_value(ctrlp,
419 PVR2_CVAL_INPUT_RADIO);
420 }
421 } else {
422 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
423 pvr2_ctrl_set_value(ctrlp,
424 PVR2_CVAL_INPUT_TV);
425 }
426 }
427 fv = vf->frequency;
428 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300429 fv = (fv * 125) / 2;
430 } else {
431 fv = fv * 62500;
432 }
Mike Iselyd8554972006-06-26 20:58:46 -0300433 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300434 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300435 break;
436 }
437
438 case VIDIOC_G_FREQUENCY:
439 {
440 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
441 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300442 int cur_input;
443 struct v4l2_tuner vt;
444 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
445 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300446 ret = pvr2_ctrl_get_value(
447 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
448 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300449 if (ret != 0) break;
450 pvr2_ctrl_get_value(
451 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
452 &cur_input);
453 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300454 vf->type = V4L2_TUNER_RADIO;
455 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300456 vf->type = V4L2_TUNER_ANALOG_TV;
457 }
Mike Isely18103c52007-01-20 00:09:47 -0300458 if (vt.capability & V4L2_TUNER_CAP_LOW) {
459 val = (val * 2) / 125;
460 } else {
461 val /= 62500;
462 }
463 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300464 break;
465 }
466
467 case VIDIOC_ENUM_FMT:
468 {
469 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
470
471 /* Only one format is supported : mpeg.*/
472 if (fd->index != 0)
473 break;
474
475 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
476 ret = 0;
477 break;
478 }
479
480 case VIDIOC_G_FMT:
481 {
482 struct v4l2_format *vf = (struct v4l2_format *)arg;
483 int val;
484 switch(vf->type) {
485 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
486 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
487 sizeof(struct v4l2_format));
488 val = 0;
489 pvr2_ctrl_get_value(
490 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
491 &val);
492 vf->fmt.pix.width = val;
493 val = 0;
494 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300495 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
496 &val);
497 vf->fmt.pix.height = val;
498 ret = 0;
499 break;
500 case V4L2_BUF_TYPE_VBI_CAPTURE:
501 // ????? Still need to figure out to do VBI correctly
502 ret = -EINVAL;
503 break;
504 default:
505 ret = -EINVAL;
506 break;
507 }
508 break;
509 }
510
511 case VIDIOC_TRY_FMT:
512 case VIDIOC_S_FMT:
513 {
514 struct v4l2_format *vf = (struct v4l2_format *)arg;
515
516 ret = 0;
517 switch(vf->type) {
518 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300519 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300520 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300521 int h = vf->fmt.pix.height;
522 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300523 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
524 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300525
Mike Iselye95a1912006-08-08 09:10:07 -0300526 lmin = pvr2_ctrl_get_min(hcp);
527 lmax = pvr2_ctrl_get_max(hcp);
Mike Isely26dd1c52008-08-31 20:55:03 -0300528 pvr2_ctrl_get_def(hcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300529 if (w == -1) {
530 w = ldef;
531 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300532 w = lmin;
533 } else if (w > lmax) {
534 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300535 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300536 lmin = pvr2_ctrl_get_min(vcp);
537 lmax = pvr2_ctrl_get_max(vcp);
Mike Isely26dd1c52008-08-31 20:55:03 -0300538 pvr2_ctrl_get_def(vcp, &ldef);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300539 if (h == -1) {
540 h = ldef;
541 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300542 h = lmin;
543 } else if (h > lmax) {
544 h = lmax;
545 }
Mike Iselyd8554972006-06-26 20:58:46 -0300546
547 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
548 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300549 vf->fmt.pix.width = w;
550 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300551
552 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300553 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
554 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300555 }
556 } break;
557 case V4L2_BUF_TYPE_VBI_CAPTURE:
558 // ????? Still need to figure out to do VBI correctly
559 ret = -EINVAL;
560 break;
561 default:
562 ret = -EINVAL;
563 break;
564 }
565 break;
566 }
567
568 case VIDIOC_STREAMON:
569 {
Joe Perches108bdd72010-04-05 16:05:39 -0300570 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300571 /* No stream defined for this node. This means
572 that we're not currently allowed to stream from
573 this node. */
574 ret = -EPERM;
575 break;
576 }
Joe Perches108bdd72010-04-05 16:05:39 -0300577 ret = pvr2_hdw_set_stream_type(hdw,pdi->config);
Mike Iselyd8554972006-06-26 20:58:46 -0300578 if (ret < 0) return ret;
579 ret = pvr2_hdw_set_streaming(hdw,!0);
580 break;
581 }
582
583 case VIDIOC_STREAMOFF:
584 {
Joe Perches108bdd72010-04-05 16:05:39 -0300585 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -0300586 /* No stream defined for this node. This means
587 that we're not currently allowed to stream from
588 this node. */
589 ret = -EPERM;
590 break;
591 }
Mike Iselyd8554972006-06-26 20:58:46 -0300592 ret = pvr2_hdw_set_streaming(hdw,0);
593 break;
594 }
595
596 case VIDIOC_QUERYCTRL:
597 {
598 struct pvr2_ctrl *cptr;
Mike Isely26dd1c52008-08-31 20:55:03 -0300599 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300600 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
601 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300602 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
603 cptr = pvr2_hdw_get_ctrl_nextv4l(
604 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
605 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
606 } else {
607 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
608 }
Mike Iselyd8554972006-06-26 20:58:46 -0300609 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300610 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300611 "QUERYCTRL id=0x%x not implemented here",
612 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300613 ret = -EINVAL;
614 break;
615 }
616
Mike Iselya761f432006-06-25 20:04:44 -0300617 pvr2_trace(PVR2_TRACE_V4LIOCTL,
618 "QUERYCTRL id=0x%x mapping name=%s (%s)",
619 vc->id,pvr2_ctrl_get_name(cptr),
620 pvr2_ctrl_get_desc(cptr));
621 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
622 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Isely26dd1c52008-08-31 20:55:03 -0300623 pvr2_ctrl_get_def(cptr, &val);
624 vc->default_value = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300625 switch (pvr2_ctrl_get_type(cptr)) {
626 case pvr2_ctl_enum:
627 vc->type = V4L2_CTRL_TYPE_MENU;
628 vc->minimum = 0;
629 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
630 vc->step = 1;
631 break;
Mike Isely33213962006-06-25 20:04:40 -0300632 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300633 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300634 vc->minimum = 0;
635 vc->maximum = 1;
636 vc->step = 1;
637 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300638 case pvr2_ctl_int:
639 vc->type = V4L2_CTRL_TYPE_INTEGER;
640 vc->minimum = pvr2_ctrl_get_min(cptr);
641 vc->maximum = pvr2_ctrl_get_max(cptr);
642 vc->step = 1;
643 break;
644 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300645 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300646 "QUERYCTRL id=0x%x name=%s not mappable",
647 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300648 ret = -EINVAL;
649 break;
650 }
651 break;
652 }
653
654 case VIDIOC_QUERYMENU:
655 {
656 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
657 unsigned int cnt = 0;
658 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
659 vm->index,
660 vm->name,sizeof(vm->name)-1,
661 &cnt);
662 vm->name[cnt] = 0;
663 break;
664 }
665
666 case VIDIOC_G_CTRL:
667 {
668 struct v4l2_control *vc = (struct v4l2_control *)arg;
669 int val = 0;
670 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
671 &val);
672 vc->value = val;
673 break;
674 }
675
676 case VIDIOC_S_CTRL:
677 {
678 struct v4l2_control *vc = (struct v4l2_control *)arg;
679 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
680 vc->value);
681 break;
682 }
683
Mike Isely1d9f8462006-06-25 20:04:58 -0300684 case VIDIOC_G_EXT_CTRLS:
685 {
686 struct v4l2_ext_controls *ctls =
687 (struct v4l2_ext_controls *)arg;
688 struct v4l2_ext_control *ctrl;
689 unsigned int idx;
690 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300691 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300692 for (idx = 0; idx < ctls->count; idx++) {
693 ctrl = ctls->controls + idx;
694 ret = pvr2_ctrl_get_value(
695 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
696 if (ret) {
697 ctls->error_idx = idx;
698 break;
699 }
700 /* Ensure that if read as a 64 bit value, the user
701 will still get a hopefully sane value */
702 ctrl->value64 = 0;
703 ctrl->value = val;
704 }
705 break;
706 }
707
708 case VIDIOC_S_EXT_CTRLS:
709 {
710 struct v4l2_ext_controls *ctls =
711 (struct v4l2_ext_controls *)arg;
712 struct v4l2_ext_control *ctrl;
713 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300714 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300715 for (idx = 0; idx < ctls->count; idx++) {
716 ctrl = ctls->controls + idx;
717 ret = pvr2_ctrl_set_value(
718 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
719 ctrl->value);
720 if (ret) {
721 ctls->error_idx = idx;
722 break;
723 }
724 }
725 break;
726 }
727
728 case VIDIOC_TRY_EXT_CTRLS:
729 {
730 struct v4l2_ext_controls *ctls =
731 (struct v4l2_ext_controls *)arg;
732 struct v4l2_ext_control *ctrl;
733 struct pvr2_ctrl *pctl;
734 unsigned int idx;
735 /* For the moment just validate that the requested control
736 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300737 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300738 for (idx = 0; idx < ctls->count; idx++) {
739 ctrl = ctls->controls + idx;
740 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
741 if (!pctl) {
742 ret = -EINVAL;
743 ctls->error_idx = idx;
744 break;
745 }
746 }
747 break;
748 }
749
Mike Isely432907f2008-08-31 21:02:20 -0300750 case VIDIOC_CROPCAP:
751 {
752 struct v4l2_cropcap *cap = (struct v4l2_cropcap *)arg;
753 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
754 ret = -EINVAL;
755 break;
756 }
757 ret = pvr2_hdw_get_cropcap(hdw, cap);
758 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /* paranoia */
759 break;
760 }
761 case VIDIOC_G_CROP:
762 {
763 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
764 int val = 0;
765 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
766 ret = -EINVAL;
767 break;
768 }
769 ret = pvr2_ctrl_get_value(
770 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
771 if (ret != 0) {
772 ret = -EINVAL;
773 break;
774 }
775 crop->c.left = val;
776 ret = pvr2_ctrl_get_value(
777 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
778 if (ret != 0) {
779 ret = -EINVAL;
780 break;
781 }
782 crop->c.top = val;
783 ret = pvr2_ctrl_get_value(
784 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
785 if (ret != 0) {
786 ret = -EINVAL;
787 break;
788 }
789 crop->c.width = val;
790 ret = pvr2_ctrl_get_value(
791 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
792 if (ret != 0) {
793 ret = -EINVAL;
794 break;
795 }
796 crop->c.height = val;
797 }
798 case VIDIOC_S_CROP:
799 {
800 struct v4l2_crop *crop = (struct v4l2_crop *)arg;
Mike Isely432907f2008-08-31 21:02:20 -0300801 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
802 ret = -EINVAL;
803 break;
804 }
Mike Isely432907f2008-08-31 21:02:20 -0300805 ret = pvr2_ctrl_set_value(
806 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
807 crop->c.left);
808 if (ret != 0) {
809 ret = -EINVAL;
810 break;
811 }
812 ret = pvr2_ctrl_set_value(
813 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
814 crop->c.top);
815 if (ret != 0) {
816 ret = -EINVAL;
817 break;
818 }
819 ret = pvr2_ctrl_set_value(
820 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
821 crop->c.width);
822 if (ret != 0) {
823 ret = -EINVAL;
824 break;
825 }
826 ret = pvr2_ctrl_set_value(
827 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
828 crop->c.height);
829 if (ret != 0) {
830 ret = -EINVAL;
831 break;
832 }
833 }
Mike Iselyd8554972006-06-26 20:58:46 -0300834 case VIDIOC_LOG_STATUS:
835 {
Mike Iselyd8554972006-06-26 20:58:46 -0300836 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300837 ret = 0;
838 break;
839 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300840#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300841 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300842 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300843 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300844 u64 val;
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300845 struct v4l2_dbg_register *req = (struct v4l2_dbg_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300846 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300847 ret = pvr2_hdw_register_access(
Hans Verkuilaecde8b2008-12-30 07:14:19 -0300848 hdw, &req->match, req->reg,
849 cmd == VIDIOC_DBG_S_REGISTER, &val);
Trent Piepho52ebc762007-01-23 22:38:13 -0300850 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300851 break;
852 }
853#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300854
855 default :
Mauro Carvalho Chehab7a286cc2011-06-26 10:18:03 -0300856 ret = -ENOTTY;
Hans Verkuil08af2452010-12-24 10:33:19 -0300857 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300858 }
859
860 pvr2_hdw_commit_ctl(hdw);
861
862 if (ret < 0) {
863 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300864 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300865 "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300866 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300867 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
868 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300869 "pvr2_v4l2_do_ioctl failure, ret=%ld"
870 " command was:", ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300871 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
872 cmd);
873 }
874 }
875 } else {
876 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Hans Verkuil069b7472008-12-30 07:04:34 -0300877 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
878 ret, ret);
Mike Iselyd8554972006-06-26 20:58:46 -0300879 }
880 return ret;
881}
882
Mike Iselyd8554972006-06-26 20:58:46 -0300883static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
884{
Mike Isely0f0f2572006-12-27 23:19:42 -0300885 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300886 enum pvr2_config cfg = dip->config;
Mike Iselyd72baad2010-05-15 00:15:38 -0300887 char msg[80];
888 unsigned int mcnt;
889
890 /* Construct the unregistration message *before* we actually
891 perform the unregistration step. By doing it this way we don't
892 have to worry about potentially touching deleted resources. */
893 mcnt = scnprintf(msg, sizeof(msg) - 1,
894 "pvrusb2: unregistered device %s [%s]",
895 video_device_node_name(&dip->devbase),
896 pvr2_config_get_name(cfg));
897 msg[mcnt] = 0;
Mike Isely0f0f2572006-12-27 23:19:42 -0300898
Mike Isely16eb40d2006-12-30 18:27:32 -0300899 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300900
901 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300902 dip->v4lp = NULL;
903 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300904
905 /* Actual deallocation happens later when all internal references
906 are gone. */
907 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300908
Mike Iselyd72baad2010-05-15 00:15:38 -0300909 printk(KERN_INFO "%s\n", msg);
Mike Isely0f0f2572006-12-27 23:19:42 -0300910
Mike Iselyd8554972006-06-26 20:58:46 -0300911}
912
913
Mike Isely4a89baa2009-10-12 00:13:28 -0300914static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
915{
916 if (!dip) return;
917 if (!dip->devbase.parent) return;
918 dip->devbase.parent = NULL;
919 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
920}
921
922
Mike Iselyd8554972006-06-26 20:58:46 -0300923static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
924{
Mike Isely0f0f2572006-12-27 23:19:42 -0300925 if (vp->dev_video) {
926 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000927 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300928 }
929 if (vp->dev_radio) {
930 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000931 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300932 }
Mike Iselyd8554972006-06-26 20:58:46 -0300933
934 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
935 pvr2_channel_done(&vp->channel);
936 kfree(vp);
937}
938
939
Mike Isely75910052006-09-23 22:30:50 -0300940static void pvr2_video_device_release(struct video_device *vdev)
941{
942 struct pvr2_v4l2_dev *dev;
943 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
944 kfree(dev);
945}
946
947
Adrian Bunk07e337e2006-06-30 11:30:20 -0300948static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300949{
950 struct pvr2_v4l2 *vp;
951 vp = container_of(chp,struct pvr2_v4l2,channel);
952 if (!vp->channel.mc_head->disconnect_flag) return;
Mike Isely4a89baa2009-10-12 00:13:28 -0300953 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
954 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
Mike Iselyd8554972006-06-26 20:58:46 -0300955 if (vp->vfirst) return;
956 pvr2_v4l2_destroy_no_lock(vp);
957}
958
959
Hans Verkuil069b7472008-12-30 07:04:34 -0300960static long pvr2_v4l2_ioctl(struct file *file,
Adrian Bunk07e337e2006-06-30 11:30:20 -0300961 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300962{
963
Hans Verkuilf473bf72008-11-01 08:25:11 -0300964 return video_usercopy(file, cmd, arg, pvr2_v4l2_do_ioctl);
Mike Iselyd8554972006-06-26 20:58:46 -0300965}
966
967
Hans Verkuilbec43662008-12-30 06:58:20 -0300968static int pvr2_v4l2_release(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300969{
970 struct pvr2_v4l2_fh *fhp = file->private_data;
971 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300972 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300973
974 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
975
976 if (fhp->rhp) {
977 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300978 pvr2_hdw_set_streaming(hdw,0);
979 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300980 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300981 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300982 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300983 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300984
Hans Verkuilffb48772010-05-01 08:03:24 -0300985 v4l2_prio_close(&vp->prio, fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -0300986 file->private_data = NULL;
987
Mike Isely794b1602008-04-22 14:45:45 -0300988 if (fhp->vnext) {
989 fhp->vnext->vprev = fhp->vprev;
990 } else {
991 vp->vlast = fhp->vprev;
992 }
993 if (fhp->vprev) {
994 fhp->vprev->vnext = fhp->vnext;
995 } else {
996 vp->vfirst = fhp->vnext;
997 }
998 fhp->vnext = NULL;
999 fhp->vprev = NULL;
1000 fhp->vhead = NULL;
1001 pvr2_channel_done(&fhp->channel);
1002 pvr2_trace(PVR2_TRACE_STRUCT,
1003 "Destroying pvr_v4l2_fh id=%p",fhp);
Mike Iselye57b1c82008-04-21 03:52:34 -03001004 if (fhp->input_map) {
1005 kfree(fhp->input_map);
1006 fhp->input_map = NULL;
1007 }
Mike Isely794b1602008-04-22 14:45:45 -03001008 kfree(fhp);
1009 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
1010 pvr2_v4l2_destroy_no_lock(vp);
1011 }
Mike Iselyd8554972006-06-26 20:58:46 -03001012 return 0;
1013}
1014
1015
Hans Verkuilbec43662008-12-30 06:58:20 -03001016static int pvr2_v4l2_open(struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -03001017{
Mike Isely75910052006-09-23 22:30:50 -03001018 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -03001019 struct pvr2_v4l2_fh *fhp;
1020 struct pvr2_v4l2 *vp;
1021 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -03001022 unsigned int input_mask = 0;
Mike Iselye57b1c82008-04-21 03:52:34 -03001023 unsigned int input_cnt,idx;
Mike Isely1cb03b72008-04-21 03:47:43 -03001024 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001025
Mike Isely75910052006-09-23 22:30:50 -03001026 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -03001027
1028 vp = dip->v4lp;
1029 hdw = vp->channel.hdw;
1030
1031 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
1032
1033 if (!pvr2_hdw_dev_ok(hdw)) {
1034 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1035 "pvr2_v4l2_open: hardware not ready");
1036 return -EIO;
1037 }
1038
Mike Isely4b85dee2007-01-20 00:03:32 -03001039 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001040 if (!fhp) {
1041 return -ENOMEM;
1042 }
Mike Iselyd8554972006-06-26 20:58:46 -03001043
1044 init_waitqueue_head(&fhp->wait_data);
Joe Perches108bdd72010-04-05 16:05:39 -03001045 fhp->pdi = dip;
Mike Iselyd8554972006-06-26 20:58:46 -03001046
Mike Isely794b1602008-04-22 14:45:45 -03001047 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1048 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001049
Mike Isely1cb03b72008-04-21 03:47:43 -03001050 if (dip->v4l_type == VFL_TYPE_RADIO) {
1051 /* Opening device as a radio, legal input selection subset
1052 is just the radio. */
1053 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1054 } else {
1055 /* Opening the main V4L device, legal input selection
1056 subset includes all analog inputs. */
1057 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1058 (1 << PVR2_CVAL_INPUT_TV) |
1059 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1060 (1 << PVR2_CVAL_INPUT_SVIDEO));
1061 }
1062 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1063 if (ret) {
1064 pvr2_channel_done(&fhp->channel);
1065 pvr2_trace(PVR2_TRACE_STRUCT,
1066 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1067 fhp);
1068
1069 kfree(fhp);
1070 return ret;
1071 }
1072
Mike Iselye57b1c82008-04-21 03:52:34 -03001073 input_mask &= pvr2_hdw_get_input_available(hdw);
1074 input_cnt = 0;
1075 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1076 if (input_mask & (1 << idx)) input_cnt++;
1077 }
1078 fhp->input_cnt = input_cnt;
1079 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1080 if (!fhp->input_map) {
1081 pvr2_channel_done(&fhp->channel);
1082 pvr2_trace(PVR2_TRACE_STRUCT,
1083 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1084 fhp);
1085 kfree(fhp);
1086 return -ENOMEM;
1087 }
1088 input_cnt = 0;
1089 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1090 if (!(input_mask & (1 << idx))) continue;
1091 fhp->input_map[input_cnt++] = idx;
1092 }
1093
Mike Isely794b1602008-04-22 14:45:45 -03001094 fhp->vnext = NULL;
1095 fhp->vprev = vp->vlast;
1096 if (vp->vlast) {
1097 vp->vlast->vnext = fhp;
1098 } else {
1099 vp->vfirst = fhp;
1100 }
1101 vp->vlast = fhp;
1102 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -03001103
Mike Iselyd8554972006-06-26 20:58:46 -03001104 fhp->file = file;
1105 file->private_data = fhp;
Hans Verkuilffb48772010-05-01 08:03:24 -03001106 v4l2_prio_open(&vp->prio, &fhp->prio);
Mike Iselyd8554972006-06-26 20:58:46 -03001107
1108 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1109
1110 return 0;
1111}
1112
1113
1114static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1115{
1116 wake_up(&fhp->wait_data);
1117}
1118
1119static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1120{
1121 int ret;
1122 struct pvr2_stream *sp;
1123 struct pvr2_hdw *hdw;
1124 if (fh->rhp) return 0;
1125
Joe Perches108bdd72010-04-05 16:05:39 -03001126 if (!fh->pdi->stream) {
Mike Isely16eb40d2006-12-30 18:27:32 -03001127 /* No stream defined for this node. This means that we're
1128 not currently allowed to stream from this node. */
1129 return -EPERM;
1130 }
1131
Mike Iselyd8554972006-06-26 20:58:46 -03001132 /* First read() attempt. Try to claim the stream and start
1133 it... */
1134 if ((ret = pvr2_channel_claim_stream(&fh->channel,
Joe Perches108bdd72010-04-05 16:05:39 -03001135 fh->pdi->stream)) != 0) {
Mike Iselyd8554972006-06-26 20:58:46 -03001136 /* Someone else must already have it */
1137 return ret;
1138 }
1139
Joe Perches108bdd72010-04-05 16:05:39 -03001140 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
Mike Iselyd8554972006-06-26 20:58:46 -03001141 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001142 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001143 return -ENOMEM;
1144 }
1145
1146 hdw = fh->channel.mc_head->hdw;
Joe Perches108bdd72010-04-05 16:05:39 -03001147 sp = fh->pdi->stream->stream;
Mike Iselyd8554972006-06-26 20:58:46 -03001148 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
Joe Perches108bdd72010-04-05 16:05:39 -03001149 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
Mike Isely681c7392007-11-26 01:48:52 -03001150 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1151 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001152}
1153
1154
1155static ssize_t pvr2_v4l2_read(struct file *file,
1156 char __user *buff, size_t count, loff_t *ppos)
1157{
1158 struct pvr2_v4l2_fh *fh = file->private_data;
1159 int ret;
1160
1161 if (fh->fw_mode_flag) {
1162 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1163 char *tbuf;
1164 int c1,c2;
1165 int tcnt = 0;
1166 unsigned int offs = *ppos;
1167
1168 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1169 if (!tbuf) return -ENOMEM;
1170
1171 while (count) {
1172 c1 = count;
1173 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1174 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1175 if (c2 < 0) {
1176 tcnt = c2;
1177 break;
1178 }
1179 if (!c2) break;
1180 if (copy_to_user(buff,tbuf,c2)) {
1181 tcnt = -EFAULT;
1182 break;
1183 }
1184 offs += c2;
1185 tcnt += c2;
1186 buff += c2;
1187 count -= c2;
1188 *ppos += c2;
1189 }
1190 kfree(tbuf);
1191 return tcnt;
1192 }
1193
1194 if (!fh->rhp) {
1195 ret = pvr2_v4l2_iosetup(fh);
1196 if (ret) {
1197 return ret;
1198 }
1199 }
1200
1201 for (;;) {
1202 ret = pvr2_ioread_read(fh->rhp,buff,count);
1203 if (ret >= 0) break;
1204 if (ret != -EAGAIN) break;
1205 if (file->f_flags & O_NONBLOCK) break;
1206 /* Doing blocking I/O. Wait here. */
1207 ret = wait_event_interruptible(
1208 fh->wait_data,
1209 pvr2_ioread_avail(fh->rhp) >= 0);
1210 if (ret < 0) break;
1211 }
1212
1213 return ret;
1214}
1215
1216
1217static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1218{
1219 unsigned int mask = 0;
1220 struct pvr2_v4l2_fh *fh = file->private_data;
1221 int ret;
1222
1223 if (fh->fw_mode_flag) {
1224 mask |= POLLIN | POLLRDNORM;
1225 return mask;
1226 }
1227
1228 if (!fh->rhp) {
1229 ret = pvr2_v4l2_iosetup(fh);
1230 if (ret) return POLLERR;
1231 }
1232
1233 poll_wait(file,&fh->wait_data,wait);
1234
1235 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1236 mask |= POLLIN | POLLRDNORM;
1237 }
1238
1239 return mask;
1240}
1241
1242
Hans Verkuilbec43662008-12-30 06:58:20 -03001243static const struct v4l2_file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001244 .owner = THIS_MODULE,
1245 .open = pvr2_v4l2_open,
1246 .release = pvr2_v4l2_release,
1247 .read = pvr2_v4l2_read,
1248 .ioctl = pvr2_v4l2_ioctl,
Mike Iselyd8554972006-06-26 20:58:46 -03001249 .poll = pvr2_v4l2_poll,
1250};
1251
1252
Mike Iselyd8554972006-06-26 20:58:46 -03001253static struct video_device vdev_template = {
Mike Iselyd8554972006-06-26 20:58:46 -03001254 .fops = &vdev_fops,
1255};
1256
1257
1258static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1259 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001260 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001261{
Mike Isely4a89baa2009-10-12 00:13:28 -03001262 struct usb_device *usbdev;
Mike Iselyd8554972006-06-26 20:58:46 -03001263 int mindevnum;
1264 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001265 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001266 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001267
Mike Isely4a89baa2009-10-12 00:13:28 -03001268 usbdev = pvr2_hdw_get_dev(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001269 dip->v4l_type = v4l_type;
1270 switch (v4l_type) {
1271 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001272 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001273 dip->config = pvr2_config_mpeg;
1274 dip->minor_type = pvr2_v4l_type_video;
1275 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001276 if (!dip->stream) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001277 pr_err(KBUILD_MODNAME
1278 ": Failed to set up pvrusb2 v4l video dev"
1279 " due to missing stream instance\n");
Mike Iselyc74e0062006-12-30 18:31:22 -03001280 return;
1281 }
Mike Iselyd8554972006-06-26 20:58:46 -03001282 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001283 case VFL_TYPE_VBI:
1284 dip->config = pvr2_config_vbi;
1285 dip->minor_type = pvr2_v4l_type_vbi;
1286 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001287 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001288 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001289 dip->stream = &vp->channel.mc_head->video_stream;
1290 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001291 dip->minor_type = pvr2_v4l_type_radio;
1292 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001293 break;
1294 default:
1295 /* Bail out (this should be impossible) */
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001296 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1297 " due to unrecognized config\n");
Mike Iselyd8554972006-06-26 20:58:46 -03001298 return;
1299 }
1300
Mike Isely75910052006-09-23 22:30:50 -03001301 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1302 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001303
1304 mindevnum = -1;
1305 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001306 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1307 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001308 }
Mike Isely4a89baa2009-10-12 00:13:28 -03001309 dip->devbase.parent = &usbdev->dev;
Mike Isely16eb40d2006-12-30 18:27:32 -03001310 if ((video_register_device(&dip->devbase,
1311 dip->v4l_type, mindevnum) < 0) &&
1312 (video_register_device(&dip->devbase,
1313 dip->v4l_type, -1) < 0)) {
Mauro Carvalho Chehabbe9ed512009-01-08 09:13:42 -03001314 pr_err(KBUILD_MODNAME
1315 ": Failed to register pvrusb2 v4l device\n");
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001316 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001317
Laurent Pinchart38c7c032009-11-27 13:57:15 -03001318 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1319 video_device_node_name(&dip->devbase),
Mike Isely16eb40d2006-12-30 18:27:32 -03001320 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001321
Mike Iselyd8554972006-06-26 20:58:46 -03001322 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001323 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001324}
1325
1326
1327struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1328{
1329 struct pvr2_v4l2 *vp;
1330
Mike Isely4b85dee2007-01-20 00:03:32 -03001331 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001332 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001333 pvr2_channel_init(&vp->channel,mnp);
1334 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1335
1336 vp->channel.check_func = pvr2_v4l2_internal_check;
1337
1338 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001339 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1340 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001341 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselye57b1c82008-04-21 03:52:34 -03001342 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1343 (1 << PVR2_CVAL_INPUT_RADIO)) {
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001344 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1345 if (!vp->dev_radio) goto fail;
1346 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1347 }
Mike Iselyd8554972006-06-26 20:58:46 -03001348
1349 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001350 fail:
1351 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1352 pvr2_v4l2_destroy_no_lock(vp);
Harvey Harrisona6a3a172008-04-28 16:50:03 -07001353 return NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001354}
1355
1356/*
1357 Stuff for Emacs to see, in order to encourage consistent editing style:
1358 *** Local Variables: ***
1359 *** mode: c ***
1360 *** fill-column: 75 ***
1361 *** tab-width: 8 ***
1362 *** c-basic-offset: 8 ***
1363 *** End: ***
1364 */