blob: 249d7488e482de4fe24da8907bc3e5b4436b6b52 [file] [log] [blame]
Mike Iselyd8554972006-06-26 20:58:46 -03001/*
2 *
3 * $Id$
4 *
5 * Copyright (C) 2005 Mike Isely <isely@pobox.com>
6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <linux/kernel.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>
34
35struct pvr2_v4l2_dev;
36struct pvr2_v4l2_fh;
37struct pvr2_v4l2;
38
Mike Iselyd8554972006-06-26 20:58:46 -030039struct pvr2_v4l2_dev {
Mike Isely75910052006-09-23 22:30:50 -030040 struct video_device devbase; /* MUST be first! */
Mike Iselyd8554972006-06-26 20:58:46 -030041 struct pvr2_v4l2 *v4lp;
Mike Iselyd8554972006-06-26 20:58:46 -030042 struct pvr2_context_stream *stream;
Mike Isely16eb40d2006-12-30 18:27:32 -030043 /* Information about this device: */
44 enum pvr2_config config; /* Expected stream format */
45 int v4l_type; /* V4L defined type for this device node */
46 enum pvr2_v4l_type minor_type; /* pvr2-understood minor device type */
Mike Iselyd8554972006-06-26 20:58:46 -030047};
48
49struct pvr2_v4l2_fh {
50 struct pvr2_channel channel;
51 struct pvr2_v4l2_dev *dev_info;
52 enum v4l2_priority prio;
53 struct pvr2_ioread *rhp;
54 struct file *file;
55 struct pvr2_v4l2 *vhead;
56 struct pvr2_v4l2_fh *vnext;
57 struct pvr2_v4l2_fh *vprev;
58 wait_queue_head_t wait_data;
59 int fw_mode_flag;
Mike Iselyc74e0062006-12-30 18:31:22 -030060 int prev_input_val;
Mike Iselyd8554972006-06-26 20:58:46 -030061};
62
63struct pvr2_v4l2 {
64 struct pvr2_channel channel;
65 struct pvr2_v4l2_fh *vfirst;
66 struct pvr2_v4l2_fh *vlast;
67
68 struct v4l2_prio_state prio;
69
Mike Iselybeb0ecd2008-04-22 14:45:38 -030070 /* Map contiguous ordinal value to input id */
71 unsigned char *input_map;
72 unsigned int input_cnt;
73
Mike Isely0f0f2572006-12-27 23:19:42 -030074 /* streams - Note that these must be separately, individually,
75 * allocated pointers. This is because the v4l core is going to
76 * manage their deletion - separately, individually... */
77 struct pvr2_v4l2_dev *dev_video;
78 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030079};
80
81static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
82module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030083MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
84static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
85module_param_array(radio_nr, int, NULL, 0444);
86MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
87static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
88module_param_array(vbi_nr, int, NULL, 0444);
89MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030090
Adrian Bunk07e337e2006-06-30 11:30:20 -030091static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030092 .driver = "pvrusb2",
93 .card = "Hauppauge WinTV pvr-usb2",
94 .bus_info = "usb",
95 .version = KERNEL_VERSION(0,8,0),
96 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030097 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030098 V4L2_CAP_READWRITE),
99 .reserved = {0,0,0,0}
100};
101
Adrian Bunk07e337e2006-06-30 11:30:20 -0300102static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300103 {
104 .index = 0,
105 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
106 .flags = V4L2_FMT_FLAG_COMPRESSED,
107 .description = "MPEG1/2",
108 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
109 // breaks when I do that.
110 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
111 .reserved = { 0, 0, 0, 0 }
112 }
113};
114
115#define PVR_FORMAT_PIX 0
116#define PVR_FORMAT_VBI 1
117
Adrian Bunk07e337e2006-06-30 11:30:20 -0300118static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300119 [PVR_FORMAT_PIX] = {
120 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
121 .fmt = {
122 .pix = {
123 .width = 720,
124 .height = 576,
125 // This should really be V4L2_PIX_FMT_MPEG,
126 // but xawtv breaks when I do that.
127 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
128 .field = V4L2_FIELD_INTERLACED,
129 .bytesperline = 0, // doesn't make sense
130 // here
131 //FIXME : Don't know what to put here...
132 .sizeimage = (32*1024),
133 .colorspace = 0, // doesn't make sense here
134 .priv = 0
135 }
136 }
137 },
138 [PVR_FORMAT_VBI] = {
139 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
140 .fmt = {
141 .vbi = {
142 .sampling_rate = 27000000,
143 .offset = 248,
144 .samples_per_line = 1443,
145 .sample_format = V4L2_PIX_FMT_GREY,
146 .start = { 0, 0 },
147 .count = { 0, 0 },
148 .flags = 0,
149 .reserved = { 0, 0 }
150 }
151 }
152 }
153};
154
Mike Isely16eb40d2006-12-30 18:27:32 -0300155
156static const char *get_v4l_name(int v4l_type)
157{
158 switch (v4l_type) {
159 case VFL_TYPE_GRABBER: return "video";
160 case VFL_TYPE_RADIO: return "radio";
161 case VFL_TYPE_VBI: return "vbi";
162 default: return "?";
163 }
164}
165
166
Mike Iselyd8554972006-06-26 20:58:46 -0300167/*
168 * pvr_ioctl()
169 *
170 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
171 *
172 */
173static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
174 unsigned int cmd, void *arg)
175{
176 struct pvr2_v4l2_fh *fh = file->private_data;
177 struct pvr2_v4l2 *vp = fh->vhead;
178 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
179 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
180 int ret = -EINVAL;
181
182 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
183 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
184 }
185
186 if (!pvr2_hdw_dev_ok(hdw)) {
187 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
188 "ioctl failed - bad or no context");
189 return -EFAULT;
190 }
191
192 /* check priority */
193 switch (cmd) {
194 case VIDIOC_S_CTRL:
195 case VIDIOC_S_STD:
196 case VIDIOC_S_INPUT:
197 case VIDIOC_S_TUNER:
198 case VIDIOC_S_FREQUENCY:
199 ret = v4l2_prio_check(&vp->prio, &fh->prio);
200 if (ret)
201 return ret;
202 }
203
204 switch (cmd) {
205 case VIDIOC_QUERYCAP:
206 {
207 struct v4l2_capability *cap = arg;
208
209 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300210 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
211 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300212 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300213
214 ret = 0;
215 break;
216 }
217
218 case VIDIOC_G_PRIORITY:
219 {
220 enum v4l2_priority *p = arg;
221
222 *p = v4l2_prio_max(&vp->prio);
223 ret = 0;
224 break;
225 }
226
227 case VIDIOC_S_PRIORITY:
228 {
229 enum v4l2_priority *prio = arg;
230
231 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
232 break;
233 }
234
235 case VIDIOC_ENUMSTD:
236 {
237 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
238 int idx = vs->index;
239 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
240 break;
241 }
242
243 case VIDIOC_G_STD:
244 {
245 int val = 0;
246 ret = pvr2_ctrl_get_value(
247 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
248 *(v4l2_std_id *)arg = val;
249 break;
250 }
251
252 case VIDIOC_S_STD:
253 {
254 ret = pvr2_ctrl_set_value(
255 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
256 *(v4l2_std_id *)arg);
257 break;
258 }
259
260 case VIDIOC_ENUMINPUT:
261 {
262 struct pvr2_ctrl *cptr;
263 struct v4l2_input *vi = (struct v4l2_input *)arg;
264 struct v4l2_input tmp;
265 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300266 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300267
268 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
269
270 memset(&tmp,0,sizeof(tmp));
271 tmp.index = vi->index;
272 ret = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300273 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
274 ret = -EINVAL;
275 break;
276 }
277 val = vp->input_map[vi->index];
278 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300279 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300280 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300281 case PVR2_CVAL_INPUT_RADIO:
282 tmp.type = V4L2_INPUT_TYPE_TUNER;
283 break;
284 case PVR2_CVAL_INPUT_SVIDEO:
285 case PVR2_CVAL_INPUT_COMPOSITE:
286 tmp.type = V4L2_INPUT_TYPE_CAMERA;
287 break;
288 default:
289 ret = -EINVAL;
290 break;
291 }
292 if (ret < 0) break;
293
294 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300295 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300296 tmp.name,sizeof(tmp.name)-1,&cnt);
297 tmp.name[cnt] = 0;
298
299 /* Don't bother with audioset, since this driver currently
300 always switches the audio whenever the video is
301 switched. */
302
303 /* Handling std is a tougher problem. It doesn't make
304 sense in cases where a device might be multi-standard.
305 We could just copy out the current value for the
306 standard, but it can change over time. For now just
307 leave it zero. */
308
309 memcpy(vi, &tmp, sizeof(tmp));
310
311 ret = 0;
312 break;
313 }
314
315 case VIDIOC_G_INPUT:
316 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300317 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300318 struct pvr2_ctrl *cptr;
319 struct v4l2_input *vi = (struct v4l2_input *)arg;
320 int val;
321 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
322 val = 0;
323 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300324 vi->index = 0;
325 for (idx = 0; idx < vp->input_cnt; idx++) {
326 if (vp->input_map[idx] == val) {
327 vi->index = idx;
328 break;
329 }
330 }
Mike Iselyd8554972006-06-26 20:58:46 -0300331 break;
332 }
333
334 case VIDIOC_S_INPUT:
335 {
336 struct v4l2_input *vi = (struct v4l2_input *)arg;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300337 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
338 ret = -ERANGE;
339 break;
340 }
Mike Iselyd8554972006-06-26 20:58:46 -0300341 ret = pvr2_ctrl_set_value(
342 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300343 vp->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300344 break;
345 }
346
347 case VIDIOC_ENUMAUDIO:
348 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300349 /* pkt: FIXME: We are returning one "fake" input here
350 which could very well be called "whatever_we_like".
351 This is for apps that want to see an audio input
352 just to feel comfortable, as well as to test if
353 it can do stereo or sth. There is actually no guarantee
354 that the actual audio input cannot change behind the app's
355 back, but most applications should not mind that either.
356
357 Hopefully, mplayer people will work with us on this (this
358 whole mess is to support mplayer pvr://), or Hans will come
359 up with a more standard way to say "we have inputs but we
360 don 't want you to change them independent of video" which
361 will sort this mess.
362 */
363 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300364 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300365 if (vin->index > 0) break;
366 strncpy(vin->name, "PVRUSB2 Audio",14);
367 vin->capability = V4L2_AUDCAP_STEREO;
368 ret = 0;
369 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300370 break;
371 }
372
373 case VIDIOC_G_AUDIO:
374 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300375 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
376 struct v4l2_audio *vin = arg;
377 memset(vin,0,sizeof(*vin));
378 vin->index = 0;
379 strncpy(vin->name, "PVRUSB2 Audio",14);
380 vin->capability = V4L2_AUDCAP_STEREO;
381 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300382 break;
383 }
384
385 case VIDIOC_S_AUDIO:
386 {
387 ret = -EINVAL;
388 break;
389 }
390 case VIDIOC_G_TUNER:
391 {
392 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300393
Michael Krufky8d364362007-01-22 02:17:55 -0300394 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300395
Mike Isely18103c572007-01-20 00:09:47 -0300396 pvr2_hdw_execute_tuner_poll(hdw);
397 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300398 break;
399 }
400
401 case VIDIOC_S_TUNER:
402 {
403 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
404
405 if (vt->index != 0)
406 break;
407
408 ret = pvr2_ctrl_set_value(
409 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
410 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300411 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300412 }
413
414 case VIDIOC_S_FREQUENCY:
415 {
416 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300417 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300418 struct v4l2_tuner vt;
419 int cur_input;
420 struct pvr2_ctrl *ctrlp;
421 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
422 if (ret != 0) break;
423 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
424 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
425 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300426 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300427 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
428 pvr2_ctrl_set_value(ctrlp,
429 PVR2_CVAL_INPUT_RADIO);
430 }
431 } else {
432 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
433 pvr2_ctrl_set_value(ctrlp,
434 PVR2_CVAL_INPUT_TV);
435 }
436 }
437 fv = vf->frequency;
438 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300439 fv = (fv * 125) / 2;
440 } else {
441 fv = fv * 62500;
442 }
Mike Iselyd8554972006-06-26 20:58:46 -0300443 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300444 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300445 break;
446 }
447
448 case VIDIOC_G_FREQUENCY:
449 {
450 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
451 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300452 int cur_input;
453 struct v4l2_tuner vt;
454 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
455 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300456 ret = pvr2_ctrl_get_value(
457 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
458 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300459 if (ret != 0) break;
460 pvr2_ctrl_get_value(
461 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
462 &cur_input);
463 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300464 vf->type = V4L2_TUNER_RADIO;
465 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300466 vf->type = V4L2_TUNER_ANALOG_TV;
467 }
Mike Isely18103c572007-01-20 00:09:47 -0300468 if (vt.capability & V4L2_TUNER_CAP_LOW) {
469 val = (val * 2) / 125;
470 } else {
471 val /= 62500;
472 }
473 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300474 break;
475 }
476
477 case VIDIOC_ENUM_FMT:
478 {
479 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
480
481 /* Only one format is supported : mpeg.*/
482 if (fd->index != 0)
483 break;
484
485 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
486 ret = 0;
487 break;
488 }
489
490 case VIDIOC_G_FMT:
491 {
492 struct v4l2_format *vf = (struct v4l2_format *)arg;
493 int val;
494 switch(vf->type) {
495 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
496 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
497 sizeof(struct v4l2_format));
498 val = 0;
499 pvr2_ctrl_get_value(
500 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
501 &val);
502 vf->fmt.pix.width = val;
503 val = 0;
504 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300505 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
506 &val);
507 vf->fmt.pix.height = val;
508 ret = 0;
509 break;
510 case V4L2_BUF_TYPE_VBI_CAPTURE:
511 // ????? Still need to figure out to do VBI correctly
512 ret = -EINVAL;
513 break;
514 default:
515 ret = -EINVAL;
516 break;
517 }
518 break;
519 }
520
521 case VIDIOC_TRY_FMT:
522 case VIDIOC_S_FMT:
523 {
524 struct v4l2_format *vf = (struct v4l2_format *)arg;
525
526 ret = 0;
527 switch(vf->type) {
528 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300529 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300530 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300531 int h = vf->fmt.pix.height;
532 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300533 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
534 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300535
Mike Iselye95a1912006-08-08 09:10:07 -0300536 lmin = pvr2_ctrl_get_min(hcp);
537 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300538 ldef = pvr2_ctrl_get_def(hcp);
539 if (w == -1) {
540 w = ldef;
541 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300542 w = lmin;
543 } else if (w > lmax) {
544 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300545 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300546 lmin = pvr2_ctrl_get_min(vcp);
547 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300548 ldef = pvr2_ctrl_get_def(vcp);
549 if (h == -1) {
550 h = ldef;
551 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300552 h = lmin;
553 } else if (h > lmax) {
554 h = lmax;
555 }
Mike Iselyd8554972006-06-26 20:58:46 -0300556
557 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
558 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300559 vf->fmt.pix.width = w;
560 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300561
562 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300563 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
564 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300565 }
566 } break;
567 case V4L2_BUF_TYPE_VBI_CAPTURE:
568 // ????? Still need to figure out to do VBI correctly
569 ret = -EINVAL;
570 break;
571 default:
572 ret = -EINVAL;
573 break;
574 }
575 break;
576 }
577
578 case VIDIOC_STREAMON:
579 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300580 if (!fh->dev_info->stream) {
581 /* No stream defined for this node. This means
582 that we're not currently allowed to stream from
583 this node. */
584 ret = -EPERM;
585 break;
586 }
Mike Iselyd8554972006-06-26 20:58:46 -0300587 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
588 if (ret < 0) return ret;
589 ret = pvr2_hdw_set_streaming(hdw,!0);
590 break;
591 }
592
593 case VIDIOC_STREAMOFF:
594 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300595 if (!fh->dev_info->stream) {
596 /* No stream defined for this node. This means
597 that we're not currently allowed to stream from
598 this node. */
599 ret = -EPERM;
600 break;
601 }
Mike Iselyd8554972006-06-26 20:58:46 -0300602 ret = pvr2_hdw_set_streaming(hdw,0);
603 break;
604 }
605
606 case VIDIOC_QUERYCTRL:
607 {
608 struct pvr2_ctrl *cptr;
609 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
610 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300611 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
612 cptr = pvr2_hdw_get_ctrl_nextv4l(
613 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
614 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
615 } else {
616 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
617 }
Mike Iselyd8554972006-06-26 20:58:46 -0300618 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300619 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300620 "QUERYCTRL id=0x%x not implemented here",
621 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300622 ret = -EINVAL;
623 break;
624 }
625
Mike Iselya761f432006-06-25 20:04:44 -0300626 pvr2_trace(PVR2_TRACE_V4LIOCTL,
627 "QUERYCTRL id=0x%x mapping name=%s (%s)",
628 vc->id,pvr2_ctrl_get_name(cptr),
629 pvr2_ctrl_get_desc(cptr));
630 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
631 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300632 vc->default_value = pvr2_ctrl_get_def(cptr);
633 switch (pvr2_ctrl_get_type(cptr)) {
634 case pvr2_ctl_enum:
635 vc->type = V4L2_CTRL_TYPE_MENU;
636 vc->minimum = 0;
637 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
638 vc->step = 1;
639 break;
Mike Isely33213962006-06-25 20:04:40 -0300640 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300641 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300642 vc->minimum = 0;
643 vc->maximum = 1;
644 vc->step = 1;
645 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300646 case pvr2_ctl_int:
647 vc->type = V4L2_CTRL_TYPE_INTEGER;
648 vc->minimum = pvr2_ctrl_get_min(cptr);
649 vc->maximum = pvr2_ctrl_get_max(cptr);
650 vc->step = 1;
651 break;
652 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300653 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300654 "QUERYCTRL id=0x%x name=%s not mappable",
655 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300656 ret = -EINVAL;
657 break;
658 }
659 break;
660 }
661
662 case VIDIOC_QUERYMENU:
663 {
664 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
665 unsigned int cnt = 0;
666 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
667 vm->index,
668 vm->name,sizeof(vm->name)-1,
669 &cnt);
670 vm->name[cnt] = 0;
671 break;
672 }
673
674 case VIDIOC_G_CTRL:
675 {
676 struct v4l2_control *vc = (struct v4l2_control *)arg;
677 int val = 0;
678 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
679 &val);
680 vc->value = val;
681 break;
682 }
683
684 case VIDIOC_S_CTRL:
685 {
686 struct v4l2_control *vc = (struct v4l2_control *)arg;
687 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
688 vc->value);
689 break;
690 }
691
Mike Isely1d9f8462006-06-25 20:04:58 -0300692 case VIDIOC_G_EXT_CTRLS:
693 {
694 struct v4l2_ext_controls *ctls =
695 (struct v4l2_ext_controls *)arg;
696 struct v4l2_ext_control *ctrl;
697 unsigned int idx;
698 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300699 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300700 for (idx = 0; idx < ctls->count; idx++) {
701 ctrl = ctls->controls + idx;
702 ret = pvr2_ctrl_get_value(
703 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
704 if (ret) {
705 ctls->error_idx = idx;
706 break;
707 }
708 /* Ensure that if read as a 64 bit value, the user
709 will still get a hopefully sane value */
710 ctrl->value64 = 0;
711 ctrl->value = val;
712 }
713 break;
714 }
715
716 case VIDIOC_S_EXT_CTRLS:
717 {
718 struct v4l2_ext_controls *ctls =
719 (struct v4l2_ext_controls *)arg;
720 struct v4l2_ext_control *ctrl;
721 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300722 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300723 for (idx = 0; idx < ctls->count; idx++) {
724 ctrl = ctls->controls + idx;
725 ret = pvr2_ctrl_set_value(
726 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
727 ctrl->value);
728 if (ret) {
729 ctls->error_idx = idx;
730 break;
731 }
732 }
733 break;
734 }
735
736 case VIDIOC_TRY_EXT_CTRLS:
737 {
738 struct v4l2_ext_controls *ctls =
739 (struct v4l2_ext_controls *)arg;
740 struct v4l2_ext_control *ctrl;
741 struct pvr2_ctrl *pctl;
742 unsigned int idx;
743 /* For the moment just validate that the requested control
744 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300745 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300746 for (idx = 0; idx < ctls->count; idx++) {
747 ctrl = ctls->controls + idx;
748 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
749 if (!pctl) {
750 ret = -EINVAL;
751 ctls->error_idx = idx;
752 break;
753 }
754 }
755 break;
756 }
757
Mike Iselyd8554972006-06-26 20:58:46 -0300758 case VIDIOC_LOG_STATUS:
759 {
Mike Iselyd8554972006-06-26 20:58:46 -0300760 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300761 ret = 0;
762 break;
763 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300764#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300765 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300766 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300767 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300768 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300769 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300770 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300771 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300772 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300773 cmd == VIDIOC_DBG_S_REGISTER,&val);
774 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300775 break;
776 }
777#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300778
779 default :
780 ret = v4l_compat_translate_ioctl(inode,file,cmd,
781 arg,pvr2_v4l2_do_ioctl);
782 }
783
784 pvr2_hdw_commit_ctl(hdw);
785
786 if (ret < 0) {
787 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300788 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300789 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
790 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300791 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
792 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300793 "pvr2_v4l2_do_ioctl failure, ret=%d"
794 " command was:",ret);
795 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
796 cmd);
797 }
798 }
799 } else {
800 pvr2_trace(PVR2_TRACE_V4LIOCTL,
801 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
802 ret,ret);
803 }
804 return ret;
805}
806
807
808static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
809{
Mike Isely0f0f2572006-12-27 23:19:42 -0300810 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300811 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300812 enum pvr2_config cfg = dip->config;
813 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300814
Mike Isely16eb40d2006-12-30 18:27:32 -0300815 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300816
817 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300818 dip->v4lp = NULL;
819 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300820
821 /* Actual deallocation happens later when all internal references
822 are gone. */
823 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300824
Mike Isely16eb40d2006-12-30 18:27:32 -0300825 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
826 get_v4l_name(v4l_type),minor_id & 0x1f,
827 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300828
Mike Iselyd8554972006-06-26 20:58:46 -0300829}
830
831
832static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
833{
Mike Isely0f0f2572006-12-27 23:19:42 -0300834 if (vp->dev_video) {
835 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000836 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300837 }
838 if (vp->dev_radio) {
839 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000840 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300841 }
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300842 if (vp->input_map) {
843 kfree(vp->input_map);
844 vp->input_map = NULL;
845 }
Mike Iselyd8554972006-06-26 20:58:46 -0300846
847 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
848 pvr2_channel_done(&vp->channel);
849 kfree(vp);
850}
851
852
Mike Isely75910052006-09-23 22:30:50 -0300853static void pvr2_video_device_release(struct video_device *vdev)
854{
855 struct pvr2_v4l2_dev *dev;
856 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
857 kfree(dev);
858}
859
860
Adrian Bunk07e337e2006-06-30 11:30:20 -0300861static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300862{
863 struct pvr2_v4l2 *vp;
864 vp = container_of(chp,struct pvr2_v4l2,channel);
865 if (!vp->channel.mc_head->disconnect_flag) return;
866 if (vp->vfirst) return;
867 pvr2_v4l2_destroy_no_lock(vp);
868}
869
870
Adrian Bunk07e337e2006-06-30 11:30:20 -0300871static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
872 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300873{
874
875/* Temporary hack : use ivtv api until a v4l2 one is available. */
876#define IVTV_IOC_G_CODEC 0xFFEE7703
877#define IVTV_IOC_S_CODEC 0xFFEE7704
878 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
879 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
880}
881
882
Adrian Bunk07e337e2006-06-30 11:30:20 -0300883static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300884{
885 struct pvr2_v4l2_fh *fhp = file->private_data;
886 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300887 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300888
889 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
890
891 if (fhp->rhp) {
892 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300893 pvr2_hdw_set_streaming(hdw,0);
894 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300895 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300896 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300897 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300898 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300899
Mike Iselyd8554972006-06-26 20:58:46 -0300900 v4l2_prio_close(&vp->prio, &fhp->prio);
901 file->private_data = NULL;
902
Mike Isely794b1602008-04-22 14:45:45 -0300903 /* Restore the previous input selection, if it makes sense
904 to do so. */
905 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
906 struct pvr2_ctrl *cp;
907 int pval;
908 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
909 pvr2_ctrl_get_value(cp,&pval);
910 /* Only restore if we're still selecting the radio */
911 if (pval == PVR2_CVAL_INPUT_RADIO) {
912 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
913 pvr2_hdw_commit_ctl(hdw);
Mike Iselyc74e0062006-12-30 18:31:22 -0300914 }
Mike Isely794b1602008-04-22 14:45:45 -0300915 }
Mike Iselyc74e0062006-12-30 18:31:22 -0300916
Mike Isely794b1602008-04-22 14:45:45 -0300917 if (fhp->vnext) {
918 fhp->vnext->vprev = fhp->vprev;
919 } else {
920 vp->vlast = fhp->vprev;
921 }
922 if (fhp->vprev) {
923 fhp->vprev->vnext = fhp->vnext;
924 } else {
925 vp->vfirst = fhp->vnext;
926 }
927 fhp->vnext = NULL;
928 fhp->vprev = NULL;
929 fhp->vhead = NULL;
930 pvr2_channel_done(&fhp->channel);
931 pvr2_trace(PVR2_TRACE_STRUCT,
932 "Destroying pvr_v4l2_fh id=%p",fhp);
933 kfree(fhp);
934 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
935 pvr2_v4l2_destroy_no_lock(vp);
936 }
Mike Iselyd8554972006-06-26 20:58:46 -0300937 return 0;
938}
939
940
Adrian Bunk07e337e2006-06-30 11:30:20 -0300941static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300942{
Mike Isely75910052006-09-23 22:30:50 -0300943 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300944 struct pvr2_v4l2_fh *fhp;
945 struct pvr2_v4l2 *vp;
946 struct pvr2_hdw *hdw;
947
Mike Isely75910052006-09-23 22:30:50 -0300948 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300949
950 vp = dip->v4lp;
951 hdw = vp->channel.hdw;
952
953 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
954
955 if (!pvr2_hdw_dev_ok(hdw)) {
956 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
957 "pvr2_v4l2_open: hardware not ready");
958 return -EIO;
959 }
960
Mike Isely4b85dee2007-01-20 00:03:32 -0300961 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300962 if (!fhp) {
963 return -ENOMEM;
964 }
Mike Iselyd8554972006-06-26 20:58:46 -0300965
966 init_waitqueue_head(&fhp->wait_data);
967 fhp->dev_info = dip;
968
Mike Isely794b1602008-04-22 14:45:45 -0300969 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
970 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300971
Mike Isely794b1602008-04-22 14:45:45 -0300972 fhp->vnext = NULL;
973 fhp->vprev = vp->vlast;
974 if (vp->vlast) {
975 vp->vlast->vnext = fhp;
976 } else {
977 vp->vfirst = fhp;
978 }
979 vp->vlast = fhp;
980 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300981
Mike Isely794b1602008-04-22 14:45:45 -0300982 /* Opening the /dev/radioX device implies a mode switch.
983 So execute that here. Note that you can get the
984 IDENTICAL effect merely by opening the normal video
985 device and setting the input appropriately. */
986 if (dip->v4l_type == VFL_TYPE_RADIO) {
987 struct pvr2_ctrl *cp;
988 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
989 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
990 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
991 pvr2_hdw_commit_ctl(hdw);
992 }
Mike Iselyd8554972006-06-26 20:58:46 -0300993
994 fhp->file = file;
995 file->private_data = fhp;
996 v4l2_prio_open(&vp->prio,&fhp->prio);
997
998 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
999
1000 return 0;
1001}
1002
1003
1004static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1005{
1006 wake_up(&fhp->wait_data);
1007}
1008
1009static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1010{
1011 int ret;
1012 struct pvr2_stream *sp;
1013 struct pvr2_hdw *hdw;
1014 if (fh->rhp) return 0;
1015
Mike Isely16eb40d2006-12-30 18:27:32 -03001016 if (!fh->dev_info->stream) {
1017 /* No stream defined for this node. This means that we're
1018 not currently allowed to stream from this node. */
1019 return -EPERM;
1020 }
1021
Mike Iselyd8554972006-06-26 20:58:46 -03001022 /* First read() attempt. Try to claim the stream and start
1023 it... */
1024 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1025 fh->dev_info->stream)) != 0) {
1026 /* Someone else must already have it */
1027 return ret;
1028 }
1029
1030 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1031 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001032 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001033 return -ENOMEM;
1034 }
1035
1036 hdw = fh->channel.mc_head->hdw;
1037 sp = fh->dev_info->stream->stream;
1038 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1039 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001040 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1041 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001042}
1043
1044
1045static ssize_t pvr2_v4l2_read(struct file *file,
1046 char __user *buff, size_t count, loff_t *ppos)
1047{
1048 struct pvr2_v4l2_fh *fh = file->private_data;
1049 int ret;
1050
1051 if (fh->fw_mode_flag) {
1052 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1053 char *tbuf;
1054 int c1,c2;
1055 int tcnt = 0;
1056 unsigned int offs = *ppos;
1057
1058 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1059 if (!tbuf) return -ENOMEM;
1060
1061 while (count) {
1062 c1 = count;
1063 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1064 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1065 if (c2 < 0) {
1066 tcnt = c2;
1067 break;
1068 }
1069 if (!c2) break;
1070 if (copy_to_user(buff,tbuf,c2)) {
1071 tcnt = -EFAULT;
1072 break;
1073 }
1074 offs += c2;
1075 tcnt += c2;
1076 buff += c2;
1077 count -= c2;
1078 *ppos += c2;
1079 }
1080 kfree(tbuf);
1081 return tcnt;
1082 }
1083
1084 if (!fh->rhp) {
1085 ret = pvr2_v4l2_iosetup(fh);
1086 if (ret) {
1087 return ret;
1088 }
1089 }
1090
1091 for (;;) {
1092 ret = pvr2_ioread_read(fh->rhp,buff,count);
1093 if (ret >= 0) break;
1094 if (ret != -EAGAIN) break;
1095 if (file->f_flags & O_NONBLOCK) break;
1096 /* Doing blocking I/O. Wait here. */
1097 ret = wait_event_interruptible(
1098 fh->wait_data,
1099 pvr2_ioread_avail(fh->rhp) >= 0);
1100 if (ret < 0) break;
1101 }
1102
1103 return ret;
1104}
1105
1106
1107static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1108{
1109 unsigned int mask = 0;
1110 struct pvr2_v4l2_fh *fh = file->private_data;
1111 int ret;
1112
1113 if (fh->fw_mode_flag) {
1114 mask |= POLLIN | POLLRDNORM;
1115 return mask;
1116 }
1117
1118 if (!fh->rhp) {
1119 ret = pvr2_v4l2_iosetup(fh);
1120 if (ret) return POLLERR;
1121 }
1122
1123 poll_wait(file,&fh->wait_data,wait);
1124
1125 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1126 mask |= POLLIN | POLLRDNORM;
1127 }
1128
1129 return mask;
1130}
1131
1132
Arjan van de Venfa027c22007-02-12 00:55:33 -08001133static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001134 .owner = THIS_MODULE,
1135 .open = pvr2_v4l2_open,
1136 .release = pvr2_v4l2_release,
1137 .read = pvr2_v4l2_read,
1138 .ioctl = pvr2_v4l2_ioctl,
1139 .llseek = no_llseek,
1140 .poll = pvr2_v4l2_poll,
1141};
1142
1143
Mike Iselyd8554972006-06-26 20:58:46 -03001144static struct video_device vdev_template = {
1145 .owner = THIS_MODULE,
1146 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1147 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1148 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1149 | V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -03001150 .fops = &vdev_fops,
1151};
1152
1153
1154static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1155 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001156 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001157{
1158 int mindevnum;
1159 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001160 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001161 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001162
1163
Mike Isely16eb40d2006-12-30 18:27:32 -03001164 dip->v4l_type = v4l_type;
1165 switch (v4l_type) {
1166 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001167 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001168 dip->config = pvr2_config_mpeg;
1169 dip->minor_type = pvr2_v4l_type_video;
1170 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001171 if (!dip->stream) {
1172 err("Failed to set up pvrusb2 v4l video dev"
1173 " due to missing stream instance");
1174 return;
1175 }
Mike Iselyd8554972006-06-26 20:58:46 -03001176 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001177 case VFL_TYPE_VBI:
1178 dip->config = pvr2_config_vbi;
1179 dip->minor_type = pvr2_v4l_type_vbi;
1180 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001181 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001182 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001183 dip->stream = &vp->channel.mc_head->video_stream;
1184 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001185 dip->minor_type = pvr2_v4l_type_radio;
1186 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001187 break;
1188 default:
1189 /* Bail out (this should be impossible) */
1190 err("Failed to set up pvrusb2 v4l dev"
1191 " due to unrecognized config");
1192 return;
1193 }
1194
Mike Isely75910052006-09-23 22:30:50 -03001195 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1196 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001197
1198 mindevnum = -1;
1199 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001200 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1201 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001202 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001203 if ((video_register_device(&dip->devbase,
1204 dip->v4l_type, mindevnum) < 0) &&
1205 (video_register_device(&dip->devbase,
1206 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001207 err("Failed to register pvrusb2 v4l device");
1208 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001209
1210 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1211 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1212 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001213
Mike Iselyd8554972006-06-26 20:58:46 -03001214 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001215 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001216}
1217
1218
1219struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1220{
1221 struct pvr2_v4l2 *vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001222 struct pvr2_hdw *hdw;
1223 unsigned int input_mask,input_cnt,idx;
Mike Iselyd8554972006-06-26 20:58:46 -03001224
Mike Isely4b85dee2007-01-20 00:03:32 -03001225 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001226 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001227 pvr2_channel_init(&vp->channel,mnp);
1228 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1229
1230 vp->channel.check_func = pvr2_v4l2_internal_check;
1231
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001232 hdw = vp->channel.mc_head->hdw;
1233 input_mask = pvr2_hdw_get_input_available(hdw);
1234 input_cnt = 0;
1235 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1236 if (input_mask & (1 << idx)) input_cnt++;
1237 }
1238 vp->input_cnt = input_cnt;
1239 vp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1240 if (!vp->input_map) goto fail;
1241 input_cnt = 0;
1242 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1243 if (!(input_mask & (1 << idx))) continue;
1244 vp->input_map[input_cnt++] = idx;
1245 }
1246
Mike Iselyd8554972006-06-26 20:58:46 -03001247 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001248 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1249 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001250 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001251 if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) {
1252 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1253 if (!vp->dev_radio) goto fail;
1254 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1255 }
Mike Iselyd8554972006-06-26 20:58:46 -03001256
1257 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001258 fail:
1259 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1260 pvr2_v4l2_destroy_no_lock(vp);
1261 return 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001262}
1263
1264/*
1265 Stuff for Emacs to see, in order to encourage consistent editing style:
1266 *** Local Variables: ***
1267 *** mode: c ***
1268 *** fill-column: 75 ***
1269 *** tab-width: 8 ***
1270 *** c-basic-offset: 8 ***
1271 *** End: ***
1272 */