blob: 4563b3df8a0d3bbbab866bf2c71a5317f061acc1 [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 Isely0f0f257b2006-12-27 23:19:42 -030070 /* streams - Note that these must be separately, individually,
71 * allocated pointers. This is because the v4l core is going to
72 * manage their deletion - separately, individually... */
73 struct pvr2_v4l2_dev *dev_video;
74 struct pvr2_v4l2_dev *dev_radio;
Mike Iselyd8554972006-06-26 20:58:46 -030075};
76
77static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
78module_param_array(video_nr, int, NULL, 0444);
Mike Isely5e6862c2006-12-27 23:17:26 -030079MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
80static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
81module_param_array(radio_nr, int, NULL, 0444);
82MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
83static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
84module_param_array(vbi_nr, int, NULL, 0444);
85MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
Mike Iselyd8554972006-06-26 20:58:46 -030086
Adrian Bunk07e337e2006-06-30 11:30:20 -030087static struct v4l2_capability pvr_capability ={
Mike Iselyd8554972006-06-26 20:58:46 -030088 .driver = "pvrusb2",
89 .card = "Hauppauge WinTV pvr-usb2",
90 .bus_info = "usb",
91 .version = KERNEL_VERSION(0,8,0),
92 .capabilities = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -030093 V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
Mike Iselyd8554972006-06-26 20:58:46 -030094 V4L2_CAP_READWRITE),
95 .reserved = {0,0,0,0}
96};
97
Adrian Bunk07e337e2006-06-30 11:30:20 -030098static struct v4l2_fmtdesc pvr_fmtdesc [] = {
Mike Iselyd8554972006-06-26 20:58:46 -030099 {
100 .index = 0,
101 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
102 .flags = V4L2_FMT_FLAG_COMPRESSED,
103 .description = "MPEG1/2",
104 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
105 // breaks when I do that.
106 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
107 .reserved = { 0, 0, 0, 0 }
108 }
109};
110
111#define PVR_FORMAT_PIX 0
112#define PVR_FORMAT_VBI 1
113
Adrian Bunk07e337e2006-06-30 11:30:20 -0300114static struct v4l2_format pvr_format [] = {
Mike Iselyd8554972006-06-26 20:58:46 -0300115 [PVR_FORMAT_PIX] = {
116 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
117 .fmt = {
118 .pix = {
119 .width = 720,
120 .height = 576,
121 // This should really be V4L2_PIX_FMT_MPEG,
122 // but xawtv breaks when I do that.
123 .pixelformat = 0, // V4L2_PIX_FMT_MPEG,
124 .field = V4L2_FIELD_INTERLACED,
125 .bytesperline = 0, // doesn't make sense
126 // here
127 //FIXME : Don't know what to put here...
128 .sizeimage = (32*1024),
129 .colorspace = 0, // doesn't make sense here
130 .priv = 0
131 }
132 }
133 },
134 [PVR_FORMAT_VBI] = {
135 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
136 .fmt = {
137 .vbi = {
138 .sampling_rate = 27000000,
139 .offset = 248,
140 .samples_per_line = 1443,
141 .sample_format = V4L2_PIX_FMT_GREY,
142 .start = { 0, 0 },
143 .count = { 0, 0 },
144 .flags = 0,
145 .reserved = { 0, 0 }
146 }
147 }
148 }
149};
150
Mike Isely16eb40d2006-12-30 18:27:32 -0300151
152static const char *get_v4l_name(int v4l_type)
153{
154 switch (v4l_type) {
155 case VFL_TYPE_GRABBER: return "video";
156 case VFL_TYPE_RADIO: return "radio";
157 case VFL_TYPE_VBI: return "vbi";
158 default: return "?";
159 }
160}
161
162
Mike Iselyd8554972006-06-26 20:58:46 -0300163/*
164 * pvr_ioctl()
165 *
166 * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
167 *
168 */
169static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
170 unsigned int cmd, void *arg)
171{
172 struct pvr2_v4l2_fh *fh = file->private_data;
173 struct pvr2_v4l2 *vp = fh->vhead;
174 struct pvr2_v4l2_dev *dev_info = fh->dev_info;
175 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
176 int ret = -EINVAL;
177
178 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
179 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
180 }
181
182 if (!pvr2_hdw_dev_ok(hdw)) {
183 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
184 "ioctl failed - bad or no context");
185 return -EFAULT;
186 }
187
188 /* check priority */
189 switch (cmd) {
190 case VIDIOC_S_CTRL:
191 case VIDIOC_S_STD:
192 case VIDIOC_S_INPUT:
193 case VIDIOC_S_TUNER:
194 case VIDIOC_S_FREQUENCY:
195 ret = v4l2_prio_check(&vp->prio, &fh->prio);
196 if (ret)
197 return ret;
198 }
199
200 switch (cmd) {
201 case VIDIOC_QUERYCAP:
202 {
203 struct v4l2_capability *cap = arg;
204
205 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
Mike Isely31a18542007-04-08 01:11:47 -0300206 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
207 sizeof(cap->bus_info));
Mike Iselyd8554972006-06-26 20:58:46 -0300208
209 ret = 0;
210 break;
211 }
212
213 case VIDIOC_G_PRIORITY:
214 {
215 enum v4l2_priority *p = arg;
216
217 *p = v4l2_prio_max(&vp->prio);
218 ret = 0;
219 break;
220 }
221
222 case VIDIOC_S_PRIORITY:
223 {
224 enum v4l2_priority *prio = arg;
225
226 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
227 break;
228 }
229
230 case VIDIOC_ENUMSTD:
231 {
232 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
233 int idx = vs->index;
234 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
235 break;
236 }
237
238 case VIDIOC_G_STD:
239 {
240 int val = 0;
241 ret = pvr2_ctrl_get_value(
242 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
243 *(v4l2_std_id *)arg = val;
244 break;
245 }
246
247 case VIDIOC_S_STD:
248 {
249 ret = pvr2_ctrl_set_value(
250 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
251 *(v4l2_std_id *)arg);
252 break;
253 }
254
255 case VIDIOC_ENUMINPUT:
256 {
257 struct pvr2_ctrl *cptr;
258 struct v4l2_input *vi = (struct v4l2_input *)arg;
259 struct v4l2_input tmp;
260 unsigned int cnt;
261
262 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
263
264 memset(&tmp,0,sizeof(tmp));
265 tmp.index = vi->index;
266 ret = 0;
267 switch (vi->index) {
268 case PVR2_CVAL_INPUT_TV:
269 case PVR2_CVAL_INPUT_RADIO:
270 tmp.type = V4L2_INPUT_TYPE_TUNER;
271 break;
272 case PVR2_CVAL_INPUT_SVIDEO:
273 case PVR2_CVAL_INPUT_COMPOSITE:
274 tmp.type = V4L2_INPUT_TYPE_CAMERA;
275 break;
276 default:
277 ret = -EINVAL;
278 break;
279 }
280 if (ret < 0) break;
281
282 cnt = 0;
283 pvr2_ctrl_get_valname(cptr,vi->index,
284 tmp.name,sizeof(tmp.name)-1,&cnt);
285 tmp.name[cnt] = 0;
286
287 /* Don't bother with audioset, since this driver currently
288 always switches the audio whenever the video is
289 switched. */
290
291 /* Handling std is a tougher problem. It doesn't make
292 sense in cases where a device might be multi-standard.
293 We could just copy out the current value for the
294 standard, but it can change over time. For now just
295 leave it zero. */
296
297 memcpy(vi, &tmp, sizeof(tmp));
298
299 ret = 0;
300 break;
301 }
302
303 case VIDIOC_G_INPUT:
304 {
305 struct pvr2_ctrl *cptr;
306 struct v4l2_input *vi = (struct v4l2_input *)arg;
307 int val;
308 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
309 val = 0;
310 ret = pvr2_ctrl_get_value(cptr,&val);
311 vi->index = val;
312 break;
313 }
314
315 case VIDIOC_S_INPUT:
316 {
317 struct v4l2_input *vi = (struct v4l2_input *)arg;
318 ret = pvr2_ctrl_set_value(
319 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
320 vi->index);
321 break;
322 }
323
324 case VIDIOC_ENUMAUDIO:
325 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300326 /* pkt: FIXME: We are returning one "fake" input here
327 which could very well be called "whatever_we_like".
328 This is for apps that want to see an audio input
329 just to feel comfortable, as well as to test if
330 it can do stereo or sth. There is actually no guarantee
331 that the actual audio input cannot change behind the app's
332 back, but most applications should not mind that either.
333
334 Hopefully, mplayer people will work with us on this (this
335 whole mess is to support mplayer pvr://), or Hans will come
336 up with a more standard way to say "we have inputs but we
337 don 't want you to change them independent of video" which
338 will sort this mess.
339 */
340 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300341 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300342 if (vin->index > 0) break;
343 strncpy(vin->name, "PVRUSB2 Audio",14);
344 vin->capability = V4L2_AUDCAP_STEREO;
345 ret = 0;
346 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300347 break;
348 }
349
350 case VIDIOC_G_AUDIO:
351 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300352 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
353 struct v4l2_audio *vin = arg;
354 memset(vin,0,sizeof(*vin));
355 vin->index = 0;
356 strncpy(vin->name, "PVRUSB2 Audio",14);
357 vin->capability = V4L2_AUDCAP_STEREO;
358 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300359 break;
360 }
361
362 case VIDIOC_S_AUDIO:
363 {
364 ret = -EINVAL;
365 break;
366 }
367 case VIDIOC_G_TUNER:
368 {
369 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300370
Michael Krufky8d364362007-01-22 02:17:55 -0300371 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300372
Mike Isely18103c572007-01-20 00:09:47 -0300373 pvr2_hdw_execute_tuner_poll(hdw);
374 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300375 break;
376 }
377
378 case VIDIOC_S_TUNER:
379 {
380 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
381
382 if (vt->index != 0)
383 break;
384
385 ret = pvr2_ctrl_set_value(
386 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
387 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300388 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300389 }
390
391 case VIDIOC_S_FREQUENCY:
392 {
393 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300394 unsigned long fv;
Mike Isely18103c572007-01-20 00:09:47 -0300395 struct v4l2_tuner vt;
396 int cur_input;
397 struct pvr2_ctrl *ctrlp;
398 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
399 if (ret != 0) break;
400 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
401 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
402 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300403 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c572007-01-20 00:09:47 -0300404 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
405 pvr2_ctrl_set_value(ctrlp,
406 PVR2_CVAL_INPUT_RADIO);
407 }
408 } else {
409 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
410 pvr2_ctrl_set_value(ctrlp,
411 PVR2_CVAL_INPUT_TV);
412 }
413 }
414 fv = vf->frequency;
415 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300416 fv = (fv * 125) / 2;
417 } else {
418 fv = fv * 62500;
419 }
Mike Iselyd8554972006-06-26 20:58:46 -0300420 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300421 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300422 break;
423 }
424
425 case VIDIOC_G_FREQUENCY:
426 {
427 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
428 int val = 0;
Mike Isely18103c572007-01-20 00:09:47 -0300429 int cur_input;
430 struct v4l2_tuner vt;
431 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
432 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300433 ret = pvr2_ctrl_get_value(
434 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
435 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300436 if (ret != 0) break;
437 pvr2_ctrl_get_value(
438 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
439 &cur_input);
440 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300441 vf->type = V4L2_TUNER_RADIO;
442 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300443 vf->type = V4L2_TUNER_ANALOG_TV;
444 }
Mike Isely18103c572007-01-20 00:09:47 -0300445 if (vt.capability & V4L2_TUNER_CAP_LOW) {
446 val = (val * 2) / 125;
447 } else {
448 val /= 62500;
449 }
450 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300451 break;
452 }
453
454 case VIDIOC_ENUM_FMT:
455 {
456 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
457
458 /* Only one format is supported : mpeg.*/
459 if (fd->index != 0)
460 break;
461
462 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
463 ret = 0;
464 break;
465 }
466
467 case VIDIOC_G_FMT:
468 {
469 struct v4l2_format *vf = (struct v4l2_format *)arg;
470 int val;
471 switch(vf->type) {
472 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
473 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
474 sizeof(struct v4l2_format));
475 val = 0;
476 pvr2_ctrl_get_value(
477 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
478 &val);
479 vf->fmt.pix.width = val;
480 val = 0;
481 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300482 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
483 &val);
484 vf->fmt.pix.height = val;
485 ret = 0;
486 break;
487 case V4L2_BUF_TYPE_VBI_CAPTURE:
488 // ????? Still need to figure out to do VBI correctly
489 ret = -EINVAL;
490 break;
491 default:
492 ret = -EINVAL;
493 break;
494 }
495 break;
496 }
497
498 case VIDIOC_TRY_FMT:
499 case VIDIOC_S_FMT:
500 {
501 struct v4l2_format *vf = (struct v4l2_format *)arg;
502
503 ret = 0;
504 switch(vf->type) {
505 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300506 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300507 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300508 int h = vf->fmt.pix.height;
509 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300510 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
511 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300512
Mike Iselye95a1912006-08-08 09:10:07 -0300513 lmin = pvr2_ctrl_get_min(hcp);
514 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300515 ldef = pvr2_ctrl_get_def(hcp);
516 if (w == -1) {
517 w = ldef;
518 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300519 w = lmin;
520 } else if (w > lmax) {
521 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300522 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300523 lmin = pvr2_ctrl_get_min(vcp);
524 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300525 ldef = pvr2_ctrl_get_def(vcp);
526 if (h == -1) {
527 h = ldef;
528 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300529 h = lmin;
530 } else if (h > lmax) {
531 h = lmax;
532 }
Mike Iselyd8554972006-06-26 20:58:46 -0300533
534 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
535 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300536 vf->fmt.pix.width = w;
537 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300538
539 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300540 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
541 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300542 }
543 } break;
544 case V4L2_BUF_TYPE_VBI_CAPTURE:
545 // ????? Still need to figure out to do VBI correctly
546 ret = -EINVAL;
547 break;
548 default:
549 ret = -EINVAL;
550 break;
551 }
552 break;
553 }
554
555 case VIDIOC_STREAMON:
556 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300557 if (!fh->dev_info->stream) {
558 /* No stream defined for this node. This means
559 that we're not currently allowed to stream from
560 this node. */
561 ret = -EPERM;
562 break;
563 }
Mike Iselyd8554972006-06-26 20:58:46 -0300564 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
565 if (ret < 0) return ret;
566 ret = pvr2_hdw_set_streaming(hdw,!0);
567 break;
568 }
569
570 case VIDIOC_STREAMOFF:
571 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300572 if (!fh->dev_info->stream) {
573 /* No stream defined for this node. This means
574 that we're not currently allowed to stream from
575 this node. */
576 ret = -EPERM;
577 break;
578 }
Mike Iselyd8554972006-06-26 20:58:46 -0300579 ret = pvr2_hdw_set_streaming(hdw,0);
580 break;
581 }
582
583 case VIDIOC_QUERYCTRL:
584 {
585 struct pvr2_ctrl *cptr;
586 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
587 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300588 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
589 cptr = pvr2_hdw_get_ctrl_nextv4l(
590 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
591 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
592 } else {
593 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
594 }
Mike Iselyd8554972006-06-26 20:58:46 -0300595 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300596 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300597 "QUERYCTRL id=0x%x not implemented here",
598 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300599 ret = -EINVAL;
600 break;
601 }
602
Mike Iselya761f432006-06-25 20:04:44 -0300603 pvr2_trace(PVR2_TRACE_V4LIOCTL,
604 "QUERYCTRL id=0x%x mapping name=%s (%s)",
605 vc->id,pvr2_ctrl_get_name(cptr),
606 pvr2_ctrl_get_desc(cptr));
607 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
608 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300609 vc->default_value = pvr2_ctrl_get_def(cptr);
610 switch (pvr2_ctrl_get_type(cptr)) {
611 case pvr2_ctl_enum:
612 vc->type = V4L2_CTRL_TYPE_MENU;
613 vc->minimum = 0;
614 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
615 vc->step = 1;
616 break;
Mike Isely33213962006-06-25 20:04:40 -0300617 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300618 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300619 vc->minimum = 0;
620 vc->maximum = 1;
621 vc->step = 1;
622 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300623 case pvr2_ctl_int:
624 vc->type = V4L2_CTRL_TYPE_INTEGER;
625 vc->minimum = pvr2_ctrl_get_min(cptr);
626 vc->maximum = pvr2_ctrl_get_max(cptr);
627 vc->step = 1;
628 break;
629 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300630 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300631 "QUERYCTRL id=0x%x name=%s not mappable",
632 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300633 ret = -EINVAL;
634 break;
635 }
636 break;
637 }
638
639 case VIDIOC_QUERYMENU:
640 {
641 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
642 unsigned int cnt = 0;
643 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
644 vm->index,
645 vm->name,sizeof(vm->name)-1,
646 &cnt);
647 vm->name[cnt] = 0;
648 break;
649 }
650
651 case VIDIOC_G_CTRL:
652 {
653 struct v4l2_control *vc = (struct v4l2_control *)arg;
654 int val = 0;
655 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
656 &val);
657 vc->value = val;
658 break;
659 }
660
661 case VIDIOC_S_CTRL:
662 {
663 struct v4l2_control *vc = (struct v4l2_control *)arg;
664 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
665 vc->value);
666 break;
667 }
668
Mike Isely1d9f8462006-06-25 20:04:58 -0300669 case VIDIOC_G_EXT_CTRLS:
670 {
671 struct v4l2_ext_controls *ctls =
672 (struct v4l2_ext_controls *)arg;
673 struct v4l2_ext_control *ctrl;
674 unsigned int idx;
675 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300676 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300677 for (idx = 0; idx < ctls->count; idx++) {
678 ctrl = ctls->controls + idx;
679 ret = pvr2_ctrl_get_value(
680 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
681 if (ret) {
682 ctls->error_idx = idx;
683 break;
684 }
685 /* Ensure that if read as a 64 bit value, the user
686 will still get a hopefully sane value */
687 ctrl->value64 = 0;
688 ctrl->value = val;
689 }
690 break;
691 }
692
693 case VIDIOC_S_EXT_CTRLS:
694 {
695 struct v4l2_ext_controls *ctls =
696 (struct v4l2_ext_controls *)arg;
697 struct v4l2_ext_control *ctrl;
698 unsigned int idx;
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_set_value(
703 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
704 ctrl->value);
705 if (ret) {
706 ctls->error_idx = idx;
707 break;
708 }
709 }
710 break;
711 }
712
713 case VIDIOC_TRY_EXT_CTRLS:
714 {
715 struct v4l2_ext_controls *ctls =
716 (struct v4l2_ext_controls *)arg;
717 struct v4l2_ext_control *ctrl;
718 struct pvr2_ctrl *pctl;
719 unsigned int idx;
720 /* For the moment just validate that the requested control
721 actually exists. */
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 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
726 if (!pctl) {
727 ret = -EINVAL;
728 ctls->error_idx = idx;
729 break;
730 }
731 }
732 break;
733 }
734
Mike Iselyd8554972006-06-26 20:58:46 -0300735 case VIDIOC_LOG_STATUS:
736 {
Mike Iselyd8554972006-06-26 20:58:46 -0300737 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300738 ret = 0;
739 break;
740 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300741#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300742 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300743 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300744 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300745 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300746 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300747 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300748 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300749 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300750 cmd == VIDIOC_DBG_S_REGISTER,&val);
751 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300752 break;
753 }
754#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300755
756 default :
757 ret = v4l_compat_translate_ioctl(inode,file,cmd,
758 arg,pvr2_v4l2_do_ioctl);
759 }
760
761 pvr2_hdw_commit_ctl(hdw);
762
763 if (ret < 0) {
764 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300765 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300766 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
767 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300768 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
769 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300770 "pvr2_v4l2_do_ioctl failure, ret=%d"
771 " command was:",ret);
772 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
773 cmd);
774 }
775 }
776 } else {
777 pvr2_trace(PVR2_TRACE_V4LIOCTL,
778 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
779 ret,ret);
780 }
781 return ret;
782}
783
784
785static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
786{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300787 int minor_id = dip->devbase.minor;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300788 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300789 enum pvr2_config cfg = dip->config;
790 int v4l_type = dip->v4l_type;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300791
Mike Isely16eb40d2006-12-30 18:27:32 -0300792 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300793
794 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300795 dip->v4lp = NULL;
796 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300797
798 /* Actual deallocation happens later when all internal references
799 are gone. */
800 video_unregister_device(&dip->devbase);
Mike Isely0f0f257b2006-12-27 23:19:42 -0300801
Mike Isely16eb40d2006-12-30 18:27:32 -0300802 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
803 get_v4l_name(v4l_type),minor_id & 0x1f,
804 pvr2_config_get_name(cfg));
Mike Isely0f0f257b2006-12-27 23:19:42 -0300805
Mike Iselyd8554972006-06-26 20:58:46 -0300806}
807
808
809static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
810{
Mike Isely0f0f257b2006-12-27 23:19:42 -0300811 if (vp->dev_video) {
812 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000813 vp->dev_video = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300814 }
815 if (vp->dev_radio) {
816 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000817 vp->dev_radio = NULL;
Mike Isely0f0f257b2006-12-27 23:19:42 -0300818 }
Mike Iselyd8554972006-06-26 20:58:46 -0300819
820 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
821 pvr2_channel_done(&vp->channel);
822 kfree(vp);
823}
824
825
Mike Isely75910052006-09-23 22:30:50 -0300826static void pvr2_video_device_release(struct video_device *vdev)
827{
828 struct pvr2_v4l2_dev *dev;
829 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
830 kfree(dev);
831}
832
833
Adrian Bunk07e337e2006-06-30 11:30:20 -0300834static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300835{
836 struct pvr2_v4l2 *vp;
837 vp = container_of(chp,struct pvr2_v4l2,channel);
838 if (!vp->channel.mc_head->disconnect_flag) return;
839 if (vp->vfirst) return;
840 pvr2_v4l2_destroy_no_lock(vp);
841}
842
843
Adrian Bunk07e337e2006-06-30 11:30:20 -0300844static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
845 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300846{
847
848/* Temporary hack : use ivtv api until a v4l2 one is available. */
849#define IVTV_IOC_G_CODEC 0xFFEE7703
850#define IVTV_IOC_S_CODEC 0xFFEE7704
851 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
852 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
853}
854
855
Adrian Bunk07e337e2006-06-30 11:30:20 -0300856static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300857{
858 struct pvr2_v4l2_fh *fhp = file->private_data;
859 struct pvr2_v4l2 *vp = fhp->vhead;
860 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300861 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300862
863 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
864
865 if (fhp->rhp) {
866 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300867 pvr2_hdw_set_streaming(hdw,0);
868 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300869 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300870 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300871 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300872 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300873
Mike Iselyd8554972006-06-26 20:58:46 -0300874 v4l2_prio_close(&vp->prio, &fhp->prio);
875 file->private_data = NULL;
876
877 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300878 /* Restore the previous input selection, if it makes sense
879 to do so. */
880 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
881 struct pvr2_ctrl *cp;
882 int pval;
883 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
884 pvr2_ctrl_get_value(cp,&pval);
885 /* Only restore if we're still selecting the radio */
886 if (pval == PVR2_CVAL_INPUT_RADIO) {
887 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
888 pvr2_hdw_commit_ctl(hdw);
889 }
890 }
891
Mike Iselyd8554972006-06-26 20:58:46 -0300892 if (fhp->vnext) {
893 fhp->vnext->vprev = fhp->vprev;
894 } else {
895 vp->vlast = fhp->vprev;
896 }
897 if (fhp->vprev) {
898 fhp->vprev->vnext = fhp->vnext;
899 } else {
900 vp->vfirst = fhp->vnext;
901 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300902 fhp->vnext = NULL;
903 fhp->vprev = NULL;
904 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300905 pvr2_channel_done(&fhp->channel);
906 pvr2_trace(PVR2_TRACE_STRUCT,
907 "Destroying pvr_v4l2_fh id=%p",fhp);
908 kfree(fhp);
909 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
910 pvr2_v4l2_destroy_no_lock(vp);
911 }
912 } while (0); pvr2_context_exit(mp);
913 return 0;
914}
915
916
Adrian Bunk07e337e2006-06-30 11:30:20 -0300917static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300918{
Mike Isely75910052006-09-23 22:30:50 -0300919 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300920 struct pvr2_v4l2_fh *fhp;
921 struct pvr2_v4l2 *vp;
922 struct pvr2_hdw *hdw;
923
Mike Isely75910052006-09-23 22:30:50 -0300924 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300925
926 vp = dip->v4lp;
927 hdw = vp->channel.hdw;
928
929 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
930
931 if (!pvr2_hdw_dev_ok(hdw)) {
932 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
933 "pvr2_v4l2_open: hardware not ready");
934 return -EIO;
935 }
936
Mike Isely4b85dee2007-01-20 00:03:32 -0300937 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300938 if (!fhp) {
939 return -ENOMEM;
940 }
Mike Iselyd8554972006-06-26 20:58:46 -0300941
942 init_waitqueue_head(&fhp->wait_data);
943 fhp->dev_info = dip;
944
945 pvr2_context_enter(vp->channel.mc_head); do {
946 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
947 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300948
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300949 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300950 fhp->vprev = vp->vlast;
951 if (vp->vlast) {
952 vp->vlast->vnext = fhp;
953 } else {
954 vp->vfirst = fhp;
955 }
956 vp->vlast = fhp;
957 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300958
959 /* Opening the /dev/radioX device implies a mode switch.
960 So execute that here. Note that you can get the
961 IDENTICAL effect merely by opening the normal video
962 device and setting the input appropriately. */
963 if (dip->v4l_type == VFL_TYPE_RADIO) {
964 struct pvr2_ctrl *cp;
965 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
966 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
967 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
968 pvr2_hdw_commit_ctl(hdw);
969 }
Mike Iselyd8554972006-06-26 20:58:46 -0300970 } while (0); pvr2_context_exit(vp->channel.mc_head);
971
972 fhp->file = file;
973 file->private_data = fhp;
974 v4l2_prio_open(&vp->prio,&fhp->prio);
975
976 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
977
978 return 0;
979}
980
981
982static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
983{
984 wake_up(&fhp->wait_data);
985}
986
987static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
988{
989 int ret;
990 struct pvr2_stream *sp;
991 struct pvr2_hdw *hdw;
992 if (fh->rhp) return 0;
993
Mike Isely16eb40d2006-12-30 18:27:32 -0300994 if (!fh->dev_info->stream) {
995 /* No stream defined for this node. This means that we're
996 not currently allowed to stream from this node. */
997 return -EPERM;
998 }
999
Mike Iselyd8554972006-06-26 20:58:46 -03001000 /* First read() attempt. Try to claim the stream and start
1001 it... */
1002 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1003 fh->dev_info->stream)) != 0) {
1004 /* Someone else must already have it */
1005 return ret;
1006 }
1007
1008 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1009 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001010 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001011 return -ENOMEM;
1012 }
1013
1014 hdw = fh->channel.mc_head->hdw;
1015 sp = fh->dev_info->stream->stream;
1016 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1017 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
1018 pvr2_hdw_set_streaming(hdw,!0);
1019 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
1020
1021 return ret;
1022}
1023
1024
1025static ssize_t pvr2_v4l2_read(struct file *file,
1026 char __user *buff, size_t count, loff_t *ppos)
1027{
1028 struct pvr2_v4l2_fh *fh = file->private_data;
1029 int ret;
1030
1031 if (fh->fw_mode_flag) {
1032 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1033 char *tbuf;
1034 int c1,c2;
1035 int tcnt = 0;
1036 unsigned int offs = *ppos;
1037
1038 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1039 if (!tbuf) return -ENOMEM;
1040
1041 while (count) {
1042 c1 = count;
1043 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1044 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1045 if (c2 < 0) {
1046 tcnt = c2;
1047 break;
1048 }
1049 if (!c2) break;
1050 if (copy_to_user(buff,tbuf,c2)) {
1051 tcnt = -EFAULT;
1052 break;
1053 }
1054 offs += c2;
1055 tcnt += c2;
1056 buff += c2;
1057 count -= c2;
1058 *ppos += c2;
1059 }
1060 kfree(tbuf);
1061 return tcnt;
1062 }
1063
1064 if (!fh->rhp) {
1065 ret = pvr2_v4l2_iosetup(fh);
1066 if (ret) {
1067 return ret;
1068 }
1069 }
1070
1071 for (;;) {
1072 ret = pvr2_ioread_read(fh->rhp,buff,count);
1073 if (ret >= 0) break;
1074 if (ret != -EAGAIN) break;
1075 if (file->f_flags & O_NONBLOCK) break;
1076 /* Doing blocking I/O. Wait here. */
1077 ret = wait_event_interruptible(
1078 fh->wait_data,
1079 pvr2_ioread_avail(fh->rhp) >= 0);
1080 if (ret < 0) break;
1081 }
1082
1083 return ret;
1084}
1085
1086
1087static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1088{
1089 unsigned int mask = 0;
1090 struct pvr2_v4l2_fh *fh = file->private_data;
1091 int ret;
1092
1093 if (fh->fw_mode_flag) {
1094 mask |= POLLIN | POLLRDNORM;
1095 return mask;
1096 }
1097
1098 if (!fh->rhp) {
1099 ret = pvr2_v4l2_iosetup(fh);
1100 if (ret) return POLLERR;
1101 }
1102
1103 poll_wait(file,&fh->wait_data,wait);
1104
1105 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1106 mask |= POLLIN | POLLRDNORM;
1107 }
1108
1109 return mask;
1110}
1111
1112
Arjan van de Venfa027c22007-02-12 00:55:33 -08001113static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001114 .owner = THIS_MODULE,
1115 .open = pvr2_v4l2_open,
1116 .release = pvr2_v4l2_release,
1117 .read = pvr2_v4l2_read,
1118 .ioctl = pvr2_v4l2_ioctl,
1119 .llseek = no_llseek,
1120 .poll = pvr2_v4l2_poll,
1121};
1122
1123
1124#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1125
1126static struct video_device vdev_template = {
1127 .owner = THIS_MODULE,
1128 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1129 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1130 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1131 | V4L2_CAP_READWRITE),
1132 .hardware = VID_HARDWARE_PVRUSB2,
1133 .fops = &vdev_fops,
1134};
1135
1136
1137static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1138 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001139 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001140{
1141 int mindevnum;
1142 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001143 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001144 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001145
1146
Mike Isely16eb40d2006-12-30 18:27:32 -03001147 dip->v4l_type = v4l_type;
1148 switch (v4l_type) {
1149 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001150 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001151 dip->config = pvr2_config_mpeg;
1152 dip->minor_type = pvr2_v4l_type_video;
1153 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001154 if (!dip->stream) {
1155 err("Failed to set up pvrusb2 v4l video dev"
1156 " due to missing stream instance");
1157 return;
1158 }
Mike Iselyd8554972006-06-26 20:58:46 -03001159 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001160 case VFL_TYPE_VBI:
1161 dip->config = pvr2_config_vbi;
1162 dip->minor_type = pvr2_v4l_type_vbi;
1163 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001164 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001165 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001166 dip->stream = &vp->channel.mc_head->video_stream;
1167 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001168 dip->minor_type = pvr2_v4l_type_radio;
1169 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001170 break;
1171 default:
1172 /* Bail out (this should be impossible) */
1173 err("Failed to set up pvrusb2 v4l dev"
1174 " due to unrecognized config");
1175 return;
1176 }
1177
Mike Isely75910052006-09-23 22:30:50 -03001178 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1179 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001180
1181 mindevnum = -1;
1182 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001183 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1184 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001185 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001186 if ((video_register_device(&dip->devbase,
1187 dip->v4l_type, mindevnum) < 0) &&
1188 (video_register_device(&dip->devbase,
1189 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001190 err("Failed to register pvrusb2 v4l device");
1191 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001192
1193 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1194 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1195 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001196
Mike Iselyd8554972006-06-26 20:58:46 -03001197 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001198 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001199}
1200
1201
1202struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1203{
1204 struct pvr2_v4l2 *vp;
1205
Mike Isely4b85dee2007-01-20 00:03:32 -03001206 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001207 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001208 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1209 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f257b2006-12-27 23:19:42 -03001210 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001211 kfree(vp->dev_video);
1212 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001213 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001214 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001215 }
Mike Iselyd8554972006-06-26 20:58:46 -03001216 pvr2_channel_init(&vp->channel,mnp);
1217 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1218
1219 vp->channel.check_func = pvr2_v4l2_internal_check;
1220
1221 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001222 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1223 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001224
1225 return vp;
1226}
1227
1228/*
1229 Stuff for Emacs to see, in order to encourage consistent editing style:
1230 *** Local Variables: ***
1231 *** mode: c ***
1232 *** fill-column: 75 ***
1233 *** tab-width: 8 ***
1234 *** c-basic-offset: 8 ***
1235 *** End: ***
1236 */