blob: e878c6445ae21ebce175bcbd8abcb889ca55808e [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 Isely18103c52007-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 Isely18103c52007-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 Isely18103c52007-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 Isely18103c52007-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 Isely18103c52007-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;
887 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300888 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300889
890 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
891
892 if (fhp->rhp) {
893 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300894 pvr2_hdw_set_streaming(hdw,0);
895 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300896 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300897 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300898 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300899 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300900
Mike Iselyd8554972006-06-26 20:58:46 -0300901 v4l2_prio_close(&vp->prio, &fhp->prio);
902 file->private_data = NULL;
903
904 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300905 /* Restore the previous input selection, if it makes sense
906 to do so. */
907 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
908 struct pvr2_ctrl *cp;
909 int pval;
910 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
911 pvr2_ctrl_get_value(cp,&pval);
912 /* Only restore if we're still selecting the radio */
913 if (pval == PVR2_CVAL_INPUT_RADIO) {
914 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
915 pvr2_hdw_commit_ctl(hdw);
916 }
917 }
918
Mike Iselyd8554972006-06-26 20:58:46 -0300919 if (fhp->vnext) {
920 fhp->vnext->vprev = fhp->vprev;
921 } else {
922 vp->vlast = fhp->vprev;
923 }
924 if (fhp->vprev) {
925 fhp->vprev->vnext = fhp->vnext;
926 } else {
927 vp->vfirst = fhp->vnext;
928 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300929 fhp->vnext = NULL;
930 fhp->vprev = NULL;
931 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300932 pvr2_channel_done(&fhp->channel);
933 pvr2_trace(PVR2_TRACE_STRUCT,
934 "Destroying pvr_v4l2_fh id=%p",fhp);
935 kfree(fhp);
936 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
937 pvr2_v4l2_destroy_no_lock(vp);
938 }
939 } while (0); pvr2_context_exit(mp);
940 return 0;
941}
942
943
Adrian Bunk07e337e2006-06-30 11:30:20 -0300944static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300945{
Mike Isely75910052006-09-23 22:30:50 -0300946 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300947 struct pvr2_v4l2_fh *fhp;
948 struct pvr2_v4l2 *vp;
949 struct pvr2_hdw *hdw;
950
Mike Isely75910052006-09-23 22:30:50 -0300951 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300952
953 vp = dip->v4lp;
954 hdw = vp->channel.hdw;
955
956 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
957
958 if (!pvr2_hdw_dev_ok(hdw)) {
959 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
960 "pvr2_v4l2_open: hardware not ready");
961 return -EIO;
962 }
963
Mike Isely4b85dee2007-01-20 00:03:32 -0300964 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300965 if (!fhp) {
966 return -ENOMEM;
967 }
Mike Iselyd8554972006-06-26 20:58:46 -0300968
969 init_waitqueue_head(&fhp->wait_data);
970 fhp->dev_info = dip;
971
972 pvr2_context_enter(vp->channel.mc_head); do {
973 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
974 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300975
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300976 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300977 fhp->vprev = vp->vlast;
978 if (vp->vlast) {
979 vp->vlast->vnext = fhp;
980 } else {
981 vp->vfirst = fhp;
982 }
983 vp->vlast = fhp;
984 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300985
986 /* Opening the /dev/radioX device implies a mode switch.
987 So execute that here. Note that you can get the
988 IDENTICAL effect merely by opening the normal video
989 device and setting the input appropriately. */
990 if (dip->v4l_type == VFL_TYPE_RADIO) {
991 struct pvr2_ctrl *cp;
992 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
993 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
994 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
995 pvr2_hdw_commit_ctl(hdw);
996 }
Mike Iselyd8554972006-06-26 20:58:46 -0300997 } while (0); pvr2_context_exit(vp->channel.mc_head);
998
999 fhp->file = file;
1000 file->private_data = fhp;
1001 v4l2_prio_open(&vp->prio,&fhp->prio);
1002
1003 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1004
1005 return 0;
1006}
1007
1008
1009static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1010{
1011 wake_up(&fhp->wait_data);
1012}
1013
1014static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1015{
1016 int ret;
1017 struct pvr2_stream *sp;
1018 struct pvr2_hdw *hdw;
1019 if (fh->rhp) return 0;
1020
Mike Isely16eb40d2006-12-30 18:27:32 -03001021 if (!fh->dev_info->stream) {
1022 /* No stream defined for this node. This means that we're
1023 not currently allowed to stream from this node. */
1024 return -EPERM;
1025 }
1026
Mike Iselyd8554972006-06-26 20:58:46 -03001027 /* First read() attempt. Try to claim the stream and start
1028 it... */
1029 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1030 fh->dev_info->stream)) != 0) {
1031 /* Someone else must already have it */
1032 return ret;
1033 }
1034
1035 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1036 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001037 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001038 return -ENOMEM;
1039 }
1040
1041 hdw = fh->channel.mc_head->hdw;
1042 sp = fh->dev_info->stream->stream;
1043 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1044 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001045 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1046 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001047}
1048
1049
1050static ssize_t pvr2_v4l2_read(struct file *file,
1051 char __user *buff, size_t count, loff_t *ppos)
1052{
1053 struct pvr2_v4l2_fh *fh = file->private_data;
1054 int ret;
1055
1056 if (fh->fw_mode_flag) {
1057 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1058 char *tbuf;
1059 int c1,c2;
1060 int tcnt = 0;
1061 unsigned int offs = *ppos;
1062
1063 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1064 if (!tbuf) return -ENOMEM;
1065
1066 while (count) {
1067 c1 = count;
1068 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1069 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1070 if (c2 < 0) {
1071 tcnt = c2;
1072 break;
1073 }
1074 if (!c2) break;
1075 if (copy_to_user(buff,tbuf,c2)) {
1076 tcnt = -EFAULT;
1077 break;
1078 }
1079 offs += c2;
1080 tcnt += c2;
1081 buff += c2;
1082 count -= c2;
1083 *ppos += c2;
1084 }
1085 kfree(tbuf);
1086 return tcnt;
1087 }
1088
1089 if (!fh->rhp) {
1090 ret = pvr2_v4l2_iosetup(fh);
1091 if (ret) {
1092 return ret;
1093 }
1094 }
1095
1096 for (;;) {
1097 ret = pvr2_ioread_read(fh->rhp,buff,count);
1098 if (ret >= 0) break;
1099 if (ret != -EAGAIN) break;
1100 if (file->f_flags & O_NONBLOCK) break;
1101 /* Doing blocking I/O. Wait here. */
1102 ret = wait_event_interruptible(
1103 fh->wait_data,
1104 pvr2_ioread_avail(fh->rhp) >= 0);
1105 if (ret < 0) break;
1106 }
1107
1108 return ret;
1109}
1110
1111
1112static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1113{
1114 unsigned int mask = 0;
1115 struct pvr2_v4l2_fh *fh = file->private_data;
1116 int ret;
1117
1118 if (fh->fw_mode_flag) {
1119 mask |= POLLIN | POLLRDNORM;
1120 return mask;
1121 }
1122
1123 if (!fh->rhp) {
1124 ret = pvr2_v4l2_iosetup(fh);
1125 if (ret) return POLLERR;
1126 }
1127
1128 poll_wait(file,&fh->wait_data,wait);
1129
1130 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1131 mask |= POLLIN | POLLRDNORM;
1132 }
1133
1134 return mask;
1135}
1136
1137
Arjan van de Venfa027c22007-02-12 00:55:33 -08001138static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001139 .owner = THIS_MODULE,
1140 .open = pvr2_v4l2_open,
1141 .release = pvr2_v4l2_release,
1142 .read = pvr2_v4l2_read,
1143 .ioctl = pvr2_v4l2_ioctl,
1144 .llseek = no_llseek,
1145 .poll = pvr2_v4l2_poll,
1146};
1147
1148
Mike Iselyd8554972006-06-26 20:58:46 -03001149static struct video_device vdev_template = {
1150 .owner = THIS_MODULE,
1151 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1152 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1153 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1154 | V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -03001155 .fops = &vdev_fops,
1156};
1157
1158
1159static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1160 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001161 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001162{
1163 int mindevnum;
1164 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001165 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001166 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001167
1168
Mike Isely16eb40d2006-12-30 18:27:32 -03001169 dip->v4l_type = v4l_type;
1170 switch (v4l_type) {
1171 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001172 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001173 dip->config = pvr2_config_mpeg;
1174 dip->minor_type = pvr2_v4l_type_video;
1175 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001176 if (!dip->stream) {
1177 err("Failed to set up pvrusb2 v4l video dev"
1178 " due to missing stream instance");
1179 return;
1180 }
Mike Iselyd8554972006-06-26 20:58:46 -03001181 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001182 case VFL_TYPE_VBI:
1183 dip->config = pvr2_config_vbi;
1184 dip->minor_type = pvr2_v4l_type_vbi;
1185 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001186 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001187 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001188 dip->stream = &vp->channel.mc_head->video_stream;
1189 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001190 dip->minor_type = pvr2_v4l_type_radio;
1191 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001192 break;
1193 default:
1194 /* Bail out (this should be impossible) */
1195 err("Failed to set up pvrusb2 v4l dev"
1196 " due to unrecognized config");
1197 return;
1198 }
1199
Mike Isely75910052006-09-23 22:30:50 -03001200 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1201 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001202
1203 mindevnum = -1;
1204 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001205 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1206 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001207 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001208 if ((video_register_device(&dip->devbase,
1209 dip->v4l_type, mindevnum) < 0) &&
1210 (video_register_device(&dip->devbase,
1211 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001212 err("Failed to register pvrusb2 v4l device");
1213 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001214
1215 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1216 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1217 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001218
Mike Iselyd8554972006-06-26 20:58:46 -03001219 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001220 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001221}
1222
1223
1224struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1225{
1226 struct pvr2_v4l2 *vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001227 struct pvr2_hdw *hdw;
1228 unsigned int input_mask,input_cnt,idx;
Mike Iselyd8554972006-06-26 20:58:46 -03001229
Mike Isely4b85dee2007-01-20 00:03:32 -03001230 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001231 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001232 pvr2_channel_init(&vp->channel,mnp);
1233 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1234
1235 vp->channel.check_func = pvr2_v4l2_internal_check;
1236
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001237 hdw = vp->channel.mc_head->hdw;
1238 input_mask = pvr2_hdw_get_input_available(hdw);
1239 input_cnt = 0;
1240 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1241 if (input_mask & (1 << idx)) input_cnt++;
1242 }
1243 vp->input_cnt = input_cnt;
1244 vp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1245 if (!vp->input_map) goto fail;
1246 input_cnt = 0;
1247 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1248 if (!(input_mask & (1 << idx))) continue;
1249 vp->input_map[input_cnt++] = idx;
1250 }
1251
Mike Iselyd8554972006-06-26 20:58:46 -03001252 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001253 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1254 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001255 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001256 if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) {
1257 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1258 if (!vp->dev_radio) goto fail;
1259 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1260 }
Mike Iselyd8554972006-06-26 20:58:46 -03001261
1262 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001263 fail:
1264 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1265 pvr2_v4l2_destroy_no_lock(vp);
1266 return 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001267}
1268
1269/*
1270 Stuff for Emacs to see, in order to encourage consistent editing style:
1271 *** Local Variables: ***
1272 *** mode: c ***
1273 *** fill-column: 75 ***
1274 *** tab-width: 8 ***
1275 *** c-basic-offset: 8 ***
1276 *** End: ***
1277 */