blob: b415141b28595bf6d02a16263b7c0054fd710e63 [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;
60};
61
62struct pvr2_v4l2 {
63 struct pvr2_channel channel;
64 struct pvr2_v4l2_fh *vfirst;
65 struct pvr2_v4l2_fh *vlast;
66
67 struct v4l2_prio_state prio;
68
Mike Iselybeb0ecd2008-04-22 14:45:38 -030069 /* Map contiguous ordinal value to input id */
70 unsigned char *input_map;
71 unsigned int input_cnt;
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",
94 .version = KERNEL_VERSION(0,8,0),
95 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_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
155static const char *get_v4l_name(int v4l_type)
156{
157 switch (v4l_type) {
158 case VFL_TYPE_GRABBER: return "video";
159 case VFL_TYPE_RADIO: return "radio";
160 case VFL_TYPE_VBI: return "vbi";
161 default: return "?";
162 }
163}
164
165
Mike Iselyd8554972006-06-26 20:58:46 -0300166/*
167 * pvr_ioctl()
168 *
169 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
170 *
171 */
172static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
173 unsigned int cmd, void *arg)
174{
175 struct pvr2_v4l2_fh *fh = file->private_data;
176 struct pvr2_v4l2 *vp = fh->vhead;
177 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
178 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
179 int ret = -EINVAL;
180
181 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
182 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
183 }
184
185 if (!pvr2_hdw_dev_ok(hdw)) {
186 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
187 "ioctl failed - bad or no context");
188 return -EFAULT;
189 }
190
191 /* check priority */
192 switch (cmd) {
193 case VIDIOC_S_CTRL:
194 case VIDIOC_S_STD:
195 case VIDIOC_S_INPUT:
196 case VIDIOC_S_TUNER:
197 case VIDIOC_S_FREQUENCY:
198 ret = v4l2_prio_check(&vp->prio, &fh->prio);
199 if (ret)
200 return ret;
201 }
202
203 switch (cmd) {
204 case VIDIOC_QUERYCAP:
205 {
206 struct v4l2_capability *cap = arg;
207
208 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300209 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
210 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300211 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300212
213 ret = 0;
214 break;
215 }
216
217 case VIDIOC_G_PRIORITY:
218 {
219 enum v4l2_priority *p = arg;
220
221 *p = v4l2_prio_max(&vp->prio);
222 ret = 0;
223 break;
224 }
225
226 case VIDIOC_S_PRIORITY:
227 {
228 enum v4l2_priority *prio = arg;
229
230 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
231 break;
232 }
233
234 case VIDIOC_ENUMSTD:
235 {
236 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
237 int idx = vs->index;
238 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
239 break;
240 }
241
242 case VIDIOC_G_STD:
243 {
244 int val = 0;
245 ret = pvr2_ctrl_get_value(
246 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
247 *(v4l2_std_id *)arg = val;
248 break;
249 }
250
251 case VIDIOC_S_STD:
252 {
253 ret = pvr2_ctrl_set_value(
254 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
255 *(v4l2_std_id *)arg);
256 break;
257 }
258
259 case VIDIOC_ENUMINPUT:
260 {
261 struct pvr2_ctrl *cptr;
262 struct v4l2_input *vi = (struct v4l2_input *)arg;
263 struct v4l2_input tmp;
264 unsigned int cnt;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300265 int val;
Mike Iselyd8554972006-06-26 20:58:46 -0300266
267 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
268
269 memset(&tmp,0,sizeof(tmp));
270 tmp.index = vi->index;
271 ret = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300272 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
273 ret = -EINVAL;
274 break;
275 }
276 val = vp->input_map[vi->index];
277 switch (val) {
Mike Iselyd8554972006-06-26 20:58:46 -0300278 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300279 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300280 case PVR2_CVAL_INPUT_RADIO:
281 tmp.type = V4L2_INPUT_TYPE_TUNER;
282 break;
283 case PVR2_CVAL_INPUT_SVIDEO:
284 case PVR2_CVAL_INPUT_COMPOSITE:
285 tmp.type = V4L2_INPUT_TYPE_CAMERA;
286 break;
287 default:
288 ret = -EINVAL;
289 break;
290 }
291 if (ret < 0) break;
292
293 cnt = 0;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300294 pvr2_ctrl_get_valname(cptr,val,
Mike Iselyd8554972006-06-26 20:58:46 -0300295 tmp.name,sizeof(tmp.name)-1,&cnt);
296 tmp.name[cnt] = 0;
297
298 /* Don't bother with audioset, since this driver currently
299 always switches the audio whenever the video is
300 switched. */
301
302 /* Handling std is a tougher problem. It doesn't make
303 sense in cases where a device might be multi-standard.
304 We could just copy out the current value for the
305 standard, but it can change over time. For now just
306 leave it zero. */
307
308 memcpy(vi, &tmp, sizeof(tmp));
309
310 ret = 0;
311 break;
312 }
313
314 case VIDIOC_G_INPUT:
315 {
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300316 unsigned int idx;
Mike Iselyd8554972006-06-26 20:58:46 -0300317 struct pvr2_ctrl *cptr;
318 struct v4l2_input *vi = (struct v4l2_input *)arg;
319 int val;
320 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
321 val = 0;
322 ret = pvr2_ctrl_get_value(cptr,&val);
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300323 vi->index = 0;
324 for (idx = 0; idx < vp->input_cnt; idx++) {
325 if (vp->input_map[idx] == val) {
326 vi->index = idx;
327 break;
328 }
329 }
Mike Iselyd8554972006-06-26 20:58:46 -0300330 break;
331 }
332
333 case VIDIOC_S_INPUT:
334 {
335 struct v4l2_input *vi = (struct v4l2_input *)arg;
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300336 if ((vi->index < 0) || (vi->index >= vp->input_cnt)) {
337 ret = -ERANGE;
338 break;
339 }
Mike Iselyd8554972006-06-26 20:58:46 -0300340 ret = pvr2_ctrl_set_value(
341 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300342 vp->input_map[vi->index]);
Mike Iselyd8554972006-06-26 20:58:46 -0300343 break;
344 }
345
346 case VIDIOC_ENUMAUDIO:
347 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300348 /* pkt: FIXME: We are returning one "fake" input here
349 which could very well be called "whatever_we_like".
350 This is for apps that want to see an audio input
351 just to feel comfortable, as well as to test if
352 it can do stereo or sth. There is actually no guarantee
353 that the actual audio input cannot change behind the app's
354 back, but most applications should not mind that either.
355
356 Hopefully, mplayer people will work with us on this (this
357 whole mess is to support mplayer pvr://), or Hans will come
358 up with a more standard way to say "we have inputs but we
359 don 't want you to change them independent of video" which
360 will sort this mess.
361 */
362 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300363 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300364 if (vin->index > 0) break;
365 strncpy(vin->name, "PVRUSB2 Audio",14);
366 vin->capability = V4L2_AUDCAP_STEREO;
367 ret = 0;
368 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300369 break;
370 }
371
372 case VIDIOC_G_AUDIO:
373 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300374 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
375 struct v4l2_audio *vin = arg;
376 memset(vin,0,sizeof(*vin));
377 vin->index = 0;
378 strncpy(vin->name, "PVRUSB2 Audio",14);
379 vin->capability = V4L2_AUDCAP_STEREO;
380 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300381 break;
382 }
383
384 case VIDIOC_S_AUDIO:
385 {
386 ret = -EINVAL;
387 break;
388 }
389 case VIDIOC_G_TUNER:
390 {
391 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300392
Michael Krufky8d364362007-01-22 02:17:55 -0300393 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300394
Mike Isely18103c572007-01-20 00:09:47 -0300395 pvr2_hdw_execute_tuner_poll(hdw);
396 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300397 break;
398 }
399
400 case VIDIOC_S_TUNER:
401 {
402 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
403
404 if (vt->index != 0)
405 break;
406
407 ret = pvr2_ctrl_set_value(
408 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
409 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300410 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300411 }
412
413 case VIDIOC_S_FREQUENCY:
414 {
415 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300416 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300417 struct v4l2_tuner vt;
418 int cur_input;
419 struct pvr2_ctrl *ctrlp;
420 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
421 if (ret != 0) break;
422 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
423 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
424 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300425 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300426 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
427 pvr2_ctrl_set_value(ctrlp,
428 PVR2_CVAL_INPUT_RADIO);
429 }
430 } else {
431 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
432 pvr2_ctrl_set_value(ctrlp,
433 PVR2_CVAL_INPUT_TV);
434 }
435 }
436 fv = vf->frequency;
437 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300438 fv = (fv * 125) / 2;
439 } else {
440 fv = fv * 62500;
441 }
Mike Iselyd8554972006-06-26 20:58:46 -0300442 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300443 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300444 break;
445 }
446
447 case VIDIOC_G_FREQUENCY:
448 {
449 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
450 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300451 int cur_input;
452 struct v4l2_tuner vt;
453 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
454 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300455 ret = pvr2_ctrl_get_value(
456 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
457 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300458 if (ret != 0) break;
459 pvr2_ctrl_get_value(
460 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
461 &cur_input);
462 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300463 vf->type = V4L2_TUNER_RADIO;
464 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300465 vf->type = V4L2_TUNER_ANALOG_TV;
466 }
Mike Isely18103c572007-01-20 00:09:47 -0300467 if (vt.capability & V4L2_TUNER_CAP_LOW) {
468 val = (val * 2) / 125;
469 } else {
470 val /= 62500;
471 }
472 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300473 break;
474 }
475
476 case VIDIOC_ENUM_FMT:
477 {
478 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
479
480 /* Only one format is supported : mpeg.*/
481 if (fd->index != 0)
482 break;
483
484 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
485 ret = 0;
486 break;
487 }
488
489 case VIDIOC_G_FMT:
490 {
491 struct v4l2_format *vf = (struct v4l2_format *)arg;
492 int val;
493 switch(vf->type) {
494 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
495 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
496 sizeof(struct v4l2_format));
497 val = 0;
498 pvr2_ctrl_get_value(
499 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
500 &val);
501 vf->fmt.pix.width = val;
502 val = 0;
503 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300504 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
505 &val);
506 vf->fmt.pix.height = val;
507 ret = 0;
508 break;
509 case V4L2_BUF_TYPE_VBI_CAPTURE:
510 // ????? Still need to figure out to do VBI correctly
511 ret = -EINVAL;
512 break;
513 default:
514 ret = -EINVAL;
515 break;
516 }
517 break;
518 }
519
520 case VIDIOC_TRY_FMT:
521 case VIDIOC_S_FMT:
522 {
523 struct v4l2_format *vf = (struct v4l2_format *)arg;
524
525 ret = 0;
526 switch(vf->type) {
527 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300528 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300529 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300530 int h = vf->fmt.pix.height;
531 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300532 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
533 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300534
Mike Iselye95a1912006-08-08 09:10:07 -0300535 lmin = pvr2_ctrl_get_min(hcp);
536 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300537 ldef = pvr2_ctrl_get_def(hcp);
538 if (w == -1) {
539 w = ldef;
540 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300541 w = lmin;
542 } else if (w > lmax) {
543 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300544 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300545 lmin = pvr2_ctrl_get_min(vcp);
546 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300547 ldef = pvr2_ctrl_get_def(vcp);
548 if (h == -1) {
549 h = ldef;
550 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300551 h = lmin;
552 } else if (h > lmax) {
553 h = lmax;
554 }
Mike Iselyd8554972006-06-26 20:58:46 -0300555
556 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
557 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300558 vf->fmt.pix.width = w;
559 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300560
561 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300562 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
563 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300564 }
565 } break;
566 case V4L2_BUF_TYPE_VBI_CAPTURE:
567 // ????? Still need to figure out to do VBI correctly
568 ret = -EINVAL;
569 break;
570 default:
571 ret = -EINVAL;
572 break;
573 }
574 break;
575 }
576
577 case VIDIOC_STREAMON:
578 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300579 if (!fh->dev_info->stream) {
580 /* No stream defined for this node. This means
581 that we're not currently allowed to stream from
582 this node. */
583 ret = -EPERM;
584 break;
585 }
Mike Iselyd8554972006-06-26 20:58:46 -0300586 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
587 if (ret < 0) return ret;
588 ret = pvr2_hdw_set_streaming(hdw,!0);
589 break;
590 }
591
592 case VIDIOC_STREAMOFF:
593 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300594 if (!fh->dev_info->stream) {
595 /* No stream defined for this node. This means
596 that we're not currently allowed to stream from
597 this node. */
598 ret = -EPERM;
599 break;
600 }
Mike Iselyd8554972006-06-26 20:58:46 -0300601 ret = pvr2_hdw_set_streaming(hdw,0);
602 break;
603 }
604
605 case VIDIOC_QUERYCTRL:
606 {
607 struct pvr2_ctrl *cptr;
608 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
609 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300610 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
611 cptr = pvr2_hdw_get_ctrl_nextv4l(
612 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
613 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
614 } else {
615 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
616 }
Mike Iselyd8554972006-06-26 20:58:46 -0300617 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300618 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300619 "QUERYCTRL id=0x%x not implemented here",
620 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300621 ret = -EINVAL;
622 break;
623 }
624
Mike Iselya761f432006-06-25 20:04:44 -0300625 pvr2_trace(PVR2_TRACE_V4LIOCTL,
626 "QUERYCTRL id=0x%x mapping name=%s (%s)",
627 vc->id,pvr2_ctrl_get_name(cptr),
628 pvr2_ctrl_get_desc(cptr));
629 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
630 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300631 vc->default_value = pvr2_ctrl_get_def(cptr);
632 switch (pvr2_ctrl_get_type(cptr)) {
633 case pvr2_ctl_enum:
634 vc->type = V4L2_CTRL_TYPE_MENU;
635 vc->minimum = 0;
636 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
637 vc->step = 1;
638 break;
Mike Isely33213962006-06-25 20:04:40 -0300639 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300640 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300641 vc->minimum = 0;
642 vc->maximum = 1;
643 vc->step = 1;
644 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300645 case pvr2_ctl_int:
646 vc->type = V4L2_CTRL_TYPE_INTEGER;
647 vc->minimum = pvr2_ctrl_get_min(cptr);
648 vc->maximum = pvr2_ctrl_get_max(cptr);
649 vc->step = 1;
650 break;
651 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300652 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300653 "QUERYCTRL id=0x%x name=%s not mappable",
654 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300655 ret = -EINVAL;
656 break;
657 }
658 break;
659 }
660
661 case VIDIOC_QUERYMENU:
662 {
663 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
664 unsigned int cnt = 0;
665 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
666 vm->index,
667 vm->name,sizeof(vm->name)-1,
668 &cnt);
669 vm->name[cnt] = 0;
670 break;
671 }
672
673 case VIDIOC_G_CTRL:
674 {
675 struct v4l2_control *vc = (struct v4l2_control *)arg;
676 int val = 0;
677 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
678 &val);
679 vc->value = val;
680 break;
681 }
682
683 case VIDIOC_S_CTRL:
684 {
685 struct v4l2_control *vc = (struct v4l2_control *)arg;
686 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
687 vc->value);
688 break;
689 }
690
Mike Isely1d9f8462006-06-25 20:04:58 -0300691 case VIDIOC_G_EXT_CTRLS:
692 {
693 struct v4l2_ext_controls *ctls =
694 (struct v4l2_ext_controls *)arg;
695 struct v4l2_ext_control *ctrl;
696 unsigned int idx;
697 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300698 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300699 for (idx = 0; idx < ctls->count; idx++) {
700 ctrl = ctls->controls + idx;
701 ret = pvr2_ctrl_get_value(
702 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
703 if (ret) {
704 ctls->error_idx = idx;
705 break;
706 }
707 /* Ensure that if read as a 64 bit value, the user
708 will still get a hopefully sane value */
709 ctrl->value64 = 0;
710 ctrl->value = val;
711 }
712 break;
713 }
714
715 case VIDIOC_S_EXT_CTRLS:
716 {
717 struct v4l2_ext_controls *ctls =
718 (struct v4l2_ext_controls *)arg;
719 struct v4l2_ext_control *ctrl;
720 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300721 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300722 for (idx = 0; idx < ctls->count; idx++) {
723 ctrl = ctls->controls + idx;
724 ret = pvr2_ctrl_set_value(
725 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
726 ctrl->value);
727 if (ret) {
728 ctls->error_idx = idx;
729 break;
730 }
731 }
732 break;
733 }
734
735 case VIDIOC_TRY_EXT_CTRLS:
736 {
737 struct v4l2_ext_controls *ctls =
738 (struct v4l2_ext_controls *)arg;
739 struct v4l2_ext_control *ctrl;
740 struct pvr2_ctrl *pctl;
741 unsigned int idx;
742 /* For the moment just validate that the requested control
743 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300744 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300745 for (idx = 0; idx < ctls->count; idx++) {
746 ctrl = ctls->controls + idx;
747 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
748 if (!pctl) {
749 ret = -EINVAL;
750 ctls->error_idx = idx;
751 break;
752 }
753 }
754 break;
755 }
756
Mike Iselyd8554972006-06-26 20:58:46 -0300757 case VIDIOC_LOG_STATUS:
758 {
Mike Iselyd8554972006-06-26 20:58:46 -0300759 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300760 ret = 0;
761 break;
762 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300763#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300764 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300765 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300766 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300767 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300768 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300769 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300770 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300771 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300772 cmd == VIDIOC_DBG_S_REGISTER,&val);
773 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300774 break;
775 }
776#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300777
778 default :
779 ret = v4l_compat_translate_ioctl(inode,file,cmd,
780 arg,pvr2_v4l2_do_ioctl);
781 }
782
783 pvr2_hdw_commit_ctl(hdw);
784
785 if (ret < 0) {
786 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300787 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300788 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
789 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300790 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
791 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300792 "pvr2_v4l2_do_ioctl failure, ret=%d"
793 " command was:",ret);
794 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
795 cmd);
796 }
797 }
798 } else {
799 pvr2_trace(PVR2_TRACE_V4LIOCTL,
800 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
801 ret,ret);
802 }
803 return ret;
804}
805
806
807static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
808{
Mike Isely0f0f2572006-12-27 23:19:42 -0300809 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300810 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300811 enum pvr2_config cfg = dip->config;
812 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300813
Mike Isely16eb40d2006-12-30 18:27:32 -0300814 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300815
816 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300817 dip->v4lp = NULL;
818 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300819
820 /* Actual deallocation happens later when all internal references
821 are gone. */
822 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300823
Mike Isely16eb40d2006-12-30 18:27:32 -0300824 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
825 get_v4l_name(v4l_type),minor_id & 0x1f,
826 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300827
Mike Iselyd8554972006-06-26 20:58:46 -0300828}
829
830
831static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
832{
Mike Isely0f0f2572006-12-27 23:19:42 -0300833 if (vp->dev_video) {
834 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000835 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300836 }
837 if (vp->dev_radio) {
838 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000839 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300840 }
Mike Iselybeb0ecd2008-04-22 14:45:38 -0300841 if (vp->input_map) {
842 kfree(vp->input_map);
843 vp->input_map = NULL;
844 }
Mike Iselyd8554972006-06-26 20:58:46 -0300845
846 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
847 pvr2_channel_done(&vp->channel);
848 kfree(vp);
849}
850
851
Mike Isely75910052006-09-23 22:30:50 -0300852static void pvr2_video_device_release(struct video_device *vdev)
853{
854 struct pvr2_v4l2_dev *dev;
855 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
856 kfree(dev);
857}
858
859
Adrian Bunk07e337e2006-06-30 11:30:20 -0300860static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300861{
862 struct pvr2_v4l2 *vp;
863 vp = container_of(chp,struct pvr2_v4l2,channel);
864 if (!vp->channel.mc_head->disconnect_flag) return;
865 if (vp->vfirst) return;
866 pvr2_v4l2_destroy_no_lock(vp);
867}
868
869
Adrian Bunk07e337e2006-06-30 11:30:20 -0300870static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
871 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300872{
873
874/* Temporary hack : use ivtv api until a v4l2 one is available. */
875#define IVTV_IOC_G_CODEC 0xFFEE7703
876#define IVTV_IOC_S_CODEC 0xFFEE7704
877 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
878 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
879}
880
881
Adrian Bunk07e337e2006-06-30 11:30:20 -0300882static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300883{
884 struct pvr2_v4l2_fh *fhp = file->private_data;
885 struct pvr2_v4l2 *vp = fhp->vhead;
Mike Iselyc74e0062006-12-30 18:31:22 -0300886 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300887
888 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
889
890 if (fhp->rhp) {
891 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300892 pvr2_hdw_set_streaming(hdw,0);
893 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300894 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300895 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300896 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300897 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300898
Mike Iselyd8554972006-06-26 20:58:46 -0300899 v4l2_prio_close(&vp->prio, &fhp->prio);
900 file->private_data = NULL;
901
Mike Isely794b1602008-04-22 14:45:45 -0300902 if (fhp->vnext) {
903 fhp->vnext->vprev = fhp->vprev;
904 } else {
905 vp->vlast = fhp->vprev;
906 }
907 if (fhp->vprev) {
908 fhp->vprev->vnext = fhp->vnext;
909 } else {
910 vp->vfirst = fhp->vnext;
911 }
912 fhp->vnext = NULL;
913 fhp->vprev = NULL;
914 fhp->vhead = NULL;
915 pvr2_channel_done(&fhp->channel);
916 pvr2_trace(PVR2_TRACE_STRUCT,
917 "Destroying pvr_v4l2_fh id=%p",fhp);
918 kfree(fhp);
919 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
920 pvr2_v4l2_destroy_no_lock(vp);
921 }
Mike Iselyd8554972006-06-26 20:58:46 -0300922 return 0;
923}
924
925
Adrian Bunk07e337e2006-06-30 11:30:20 -0300926static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300927{
Mike Isely75910052006-09-23 22:30:50 -0300928 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300929 struct pvr2_v4l2_fh *fhp;
930 struct pvr2_v4l2 *vp;
931 struct pvr2_hdw *hdw;
Mike Isely1cb03b72008-04-21 03:47:43 -0300932 unsigned int input_mask = 0;
933 int ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300934
Mike Isely75910052006-09-23 22:30:50 -0300935 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300936
937 vp = dip->v4lp;
938 hdw = vp->channel.hdw;
939
940 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
941
942 if (!pvr2_hdw_dev_ok(hdw)) {
943 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
944 "pvr2_v4l2_open: hardware not ready");
945 return -EIO;
946 }
947
Mike Isely4b85dee2007-01-20 00:03:32 -0300948 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300949 if (!fhp) {
950 return -ENOMEM;
951 }
Mike Iselyd8554972006-06-26 20:58:46 -0300952
953 init_waitqueue_head(&fhp->wait_data);
954 fhp->dev_info = dip;
955
Mike Isely794b1602008-04-22 14:45:45 -0300956 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
957 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300958
Mike Isely1cb03b72008-04-21 03:47:43 -0300959 if (dip->v4l_type == VFL_TYPE_RADIO) {
960 /* Opening device as a radio, legal input selection subset
961 is just the radio. */
962 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
963 } else {
964 /* Opening the main V4L device, legal input selection
965 subset includes all analog inputs. */
966 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
967 (1 << PVR2_CVAL_INPUT_TV) |
968 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
969 (1 << PVR2_CVAL_INPUT_SVIDEO));
970 }
971 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
972 if (ret) {
973 pvr2_channel_done(&fhp->channel);
974 pvr2_trace(PVR2_TRACE_STRUCT,
975 "Destroying pvr_v4l2_fh id=%p (input mask error)",
976 fhp);
977
978 kfree(fhp);
979 return ret;
980 }
981
Mike Isely794b1602008-04-22 14:45:45 -0300982 fhp->vnext = NULL;
983 fhp->vprev = vp->vlast;
984 if (vp->vlast) {
985 vp->vlast->vnext = fhp;
986 } else {
987 vp->vfirst = fhp;
988 }
989 vp->vlast = fhp;
990 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300991
Mike Iselyd8554972006-06-26 20:58:46 -0300992 fhp->file = file;
993 file->private_data = fhp;
994 v4l2_prio_open(&vp->prio,&fhp->prio);
995
996 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
997
998 return 0;
999}
1000
1001
1002static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1003{
1004 wake_up(&fhp->wait_data);
1005}
1006
1007static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1008{
1009 int ret;
1010 struct pvr2_stream *sp;
1011 struct pvr2_hdw *hdw;
1012 if (fh->rhp) return 0;
1013
Mike Isely16eb40d2006-12-30 18:27:32 -03001014 if (!fh->dev_info->stream) {
1015 /* No stream defined for this node. This means that we're
1016 not currently allowed to stream from this node. */
1017 return -EPERM;
1018 }
1019
Mike Iselyd8554972006-06-26 20:58:46 -03001020 /* First read() attempt. Try to claim the stream and start
1021 it... */
1022 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1023 fh->dev_info->stream)) != 0) {
1024 /* Someone else must already have it */
1025 return ret;
1026 }
1027
1028 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1029 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001030 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001031 return -ENOMEM;
1032 }
1033
1034 hdw = fh->channel.mc_head->hdw;
1035 sp = fh->dev_info->stream->stream;
1036 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1037 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001038 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1039 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001040}
1041
1042
1043static ssize_t pvr2_v4l2_read(struct file *file,
1044 char __user *buff, size_t count, loff_t *ppos)
1045{
1046 struct pvr2_v4l2_fh *fh = file->private_data;
1047 int ret;
1048
1049 if (fh->fw_mode_flag) {
1050 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1051 char *tbuf;
1052 int c1,c2;
1053 int tcnt = 0;
1054 unsigned int offs = *ppos;
1055
1056 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1057 if (!tbuf) return -ENOMEM;
1058
1059 while (count) {
1060 c1 = count;
1061 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1062 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1063 if (c2 < 0) {
1064 tcnt = c2;
1065 break;
1066 }
1067 if (!c2) break;
1068 if (copy_to_user(buff,tbuf,c2)) {
1069 tcnt = -EFAULT;
1070 break;
1071 }
1072 offs += c2;
1073 tcnt += c2;
1074 buff += c2;
1075 count -= c2;
1076 *ppos += c2;
1077 }
1078 kfree(tbuf);
1079 return tcnt;
1080 }
1081
1082 if (!fh->rhp) {
1083 ret = pvr2_v4l2_iosetup(fh);
1084 if (ret) {
1085 return ret;
1086 }
1087 }
1088
1089 for (;;) {
1090 ret = pvr2_ioread_read(fh->rhp,buff,count);
1091 if (ret >= 0) break;
1092 if (ret != -EAGAIN) break;
1093 if (file->f_flags & O_NONBLOCK) break;
1094 /* Doing blocking I/O. Wait here. */
1095 ret = wait_event_interruptible(
1096 fh->wait_data,
1097 pvr2_ioread_avail(fh->rhp) >= 0);
1098 if (ret < 0) break;
1099 }
1100
1101 return ret;
1102}
1103
1104
1105static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1106{
1107 unsigned int mask = 0;
1108 struct pvr2_v4l2_fh *fh = file->private_data;
1109 int ret;
1110
1111 if (fh->fw_mode_flag) {
1112 mask |= POLLIN | POLLRDNORM;
1113 return mask;
1114 }
1115
1116 if (!fh->rhp) {
1117 ret = pvr2_v4l2_iosetup(fh);
1118 if (ret) return POLLERR;
1119 }
1120
1121 poll_wait(file,&fh->wait_data,wait);
1122
1123 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1124 mask |= POLLIN | POLLRDNORM;
1125 }
1126
1127 return mask;
1128}
1129
1130
Arjan van de Venfa027c22007-02-12 00:55:33 -08001131static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001132 .owner = THIS_MODULE,
1133 .open = pvr2_v4l2_open,
1134 .release = pvr2_v4l2_release,
1135 .read = pvr2_v4l2_read,
1136 .ioctl = pvr2_v4l2_ioctl,
1137 .llseek = no_llseek,
1138 .poll = pvr2_v4l2_poll,
1139};
1140
1141
Mike Iselyd8554972006-06-26 20:58:46 -03001142static struct video_device vdev_template = {
1143 .owner = THIS_MODULE,
1144 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1145 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1146 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1147 | V4L2_CAP_READWRITE),
Mike Iselyd8554972006-06-26 20:58:46 -03001148 .fops = &vdev_fops,
1149};
1150
1151
1152static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1153 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001154 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001155{
1156 int mindevnum;
1157 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001158 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001159 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001160
1161
Mike Isely16eb40d2006-12-30 18:27:32 -03001162 dip->v4l_type = v4l_type;
1163 switch (v4l_type) {
1164 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001165 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001166 dip->config = pvr2_config_mpeg;
1167 dip->minor_type = pvr2_v4l_type_video;
1168 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001169 if (!dip->stream) {
1170 err("Failed to set up pvrusb2 v4l video dev"
1171 " due to missing stream instance");
1172 return;
1173 }
Mike Iselyd8554972006-06-26 20:58:46 -03001174 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001175 case VFL_TYPE_VBI:
1176 dip->config = pvr2_config_vbi;
1177 dip->minor_type = pvr2_v4l_type_vbi;
1178 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001179 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001180 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001181 dip->stream = &vp->channel.mc_head->video_stream;
1182 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001183 dip->minor_type = pvr2_v4l_type_radio;
1184 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001185 break;
1186 default:
1187 /* Bail out (this should be impossible) */
1188 err("Failed to set up pvrusb2 v4l dev"
1189 " due to unrecognized config");
1190 return;
1191 }
1192
Mike Isely75910052006-09-23 22:30:50 -03001193 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1194 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001195
1196 mindevnum = -1;
1197 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001198 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1199 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001200 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001201 if ((video_register_device(&dip->devbase,
1202 dip->v4l_type, mindevnum) < 0) &&
1203 (video_register_device(&dip->devbase,
1204 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001205 err("Failed to register pvrusb2 v4l device");
1206 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001207
1208 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1209 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1210 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001211
Mike Iselyd8554972006-06-26 20:58:46 -03001212 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001213 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001214}
1215
1216
1217struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1218{
1219 struct pvr2_v4l2 *vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001220 struct pvr2_hdw *hdw;
1221 unsigned int input_mask,input_cnt,idx;
Mike Iselyd8554972006-06-26 20:58:46 -03001222
Mike Isely4b85dee2007-01-20 00:03:32 -03001223 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001224 if (!vp) return vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001225 pvr2_channel_init(&vp->channel,mnp);
1226 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1227
1228 vp->channel.check_func = pvr2_v4l2_internal_check;
1229
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001230 hdw = vp->channel.mc_head->hdw;
1231 input_mask = pvr2_hdw_get_input_available(hdw);
1232 input_cnt = 0;
1233 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1234 if (input_mask & (1 << idx)) input_cnt++;
1235 }
1236 vp->input_cnt = input_cnt;
1237 vp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1238 if (!vp->input_map) goto fail;
1239 input_cnt = 0;
1240 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1241 if (!(input_mask & (1 << idx))) continue;
1242 vp->input_map[input_cnt++] = idx;
1243 }
1244
Mike Iselyd8554972006-06-26 20:58:46 -03001245 /* register streams */
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001246 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1247 if (!vp->dev_video) goto fail;
Mike Isely16eb40d2006-12-30 18:27:32 -03001248 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001249 if (input_mask & (1 << PVR2_CVAL_INPUT_RADIO)) {
1250 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1251 if (!vp->dev_radio) goto fail;
1252 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1253 }
Mike Iselyd8554972006-06-26 20:58:46 -03001254
1255 return vp;
Mike Iselybeb0ecd2008-04-22 14:45:38 -03001256 fail:
1257 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1258 pvr2_v4l2_destroy_no_lock(vp);
1259 return 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001260}
1261
1262/*
1263 Stuff for Emacs to see, in order to encourage consistent editing style:
1264 *** Local Variables: ***
1265 *** mode: c ***
1266 *** fill-column: 75 ***
1267 *** tab-width: 8 ***
1268 *** c-basic-offset: 8 ***
1269 *** End: ***
1270 */