blob: 5313d342666e4e4a0b2507d20df67d83ec42a375 [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 Isely0f0f2572006-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));
206
207 ret = 0;
208 break;
209 }
210
211 case VIDIOC_G_PRIORITY:
212 {
213 enum v4l2_priority *p = arg;
214
215 *p = v4l2_prio_max(&vp->prio);
216 ret = 0;
217 break;
218 }
219
220 case VIDIOC_S_PRIORITY:
221 {
222 enum v4l2_priority *prio = arg;
223
224 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
225 break;
226 }
227
228 case VIDIOC_ENUMSTD:
229 {
230 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
231 int idx = vs->index;
232 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
233 break;
234 }
235
236 case VIDIOC_G_STD:
237 {
238 int val = 0;
239 ret = pvr2_ctrl_get_value(
240 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
241 *(v4l2_std_id *)arg = val;
242 break;
243 }
244
245 case VIDIOC_S_STD:
246 {
247 ret = pvr2_ctrl_set_value(
248 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
249 *(v4l2_std_id *)arg);
250 break;
251 }
252
253 case VIDIOC_ENUMINPUT:
254 {
255 struct pvr2_ctrl *cptr;
256 struct v4l2_input *vi = (struct v4l2_input *)arg;
257 struct v4l2_input tmp;
258 unsigned int cnt;
259
260 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
261
262 memset(&tmp,0,sizeof(tmp));
263 tmp.index = vi->index;
264 ret = 0;
265 switch (vi->index) {
266 case PVR2_CVAL_INPUT_TV:
267 case PVR2_CVAL_INPUT_RADIO:
268 tmp.type = V4L2_INPUT_TYPE_TUNER;
269 break;
270 case PVR2_CVAL_INPUT_SVIDEO:
271 case PVR2_CVAL_INPUT_COMPOSITE:
272 tmp.type = V4L2_INPUT_TYPE_CAMERA;
273 break;
274 default:
275 ret = -EINVAL;
276 break;
277 }
278 if (ret < 0) break;
279
280 cnt = 0;
281 pvr2_ctrl_get_valname(cptr,vi->index,
282 tmp.name,sizeof(tmp.name)-1,&cnt);
283 tmp.name[cnt] = 0;
284
285 /* Don't bother with audioset, since this driver currently
286 always switches the audio whenever the video is
287 switched. */
288
289 /* Handling std is a tougher problem. It doesn't make
290 sense in cases where a device might be multi-standard.
291 We could just copy out the current value for the
292 standard, but it can change over time. For now just
293 leave it zero. */
294
295 memcpy(vi, &tmp, sizeof(tmp));
296
297 ret = 0;
298 break;
299 }
300
301 case VIDIOC_G_INPUT:
302 {
303 struct pvr2_ctrl *cptr;
304 struct v4l2_input *vi = (struct v4l2_input *)arg;
305 int val;
306 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
307 val = 0;
308 ret = pvr2_ctrl_get_value(cptr,&val);
309 vi->index = val;
310 break;
311 }
312
313 case VIDIOC_S_INPUT:
314 {
315 struct v4l2_input *vi = (struct v4l2_input *)arg;
316 ret = pvr2_ctrl_set_value(
317 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
318 vi->index);
319 break;
320 }
321
322 case VIDIOC_ENUMAUDIO:
323 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300324 /* pkt: FIXME: We are returning one "fake" input here
325 which could very well be called "whatever_we_like".
326 This is for apps that want to see an audio input
327 just to feel comfortable, as well as to test if
328 it can do stereo or sth. There is actually no guarantee
329 that the actual audio input cannot change behind the app's
330 back, but most applications should not mind that either.
331
332 Hopefully, mplayer people will work with us on this (this
333 whole mess is to support mplayer pvr://), or Hans will come
334 up with a more standard way to say "we have inputs but we
335 don 't want you to change them independent of video" which
336 will sort this mess.
337 */
338 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300339 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300340 if (vin->index > 0) break;
341 strncpy(vin->name, "PVRUSB2 Audio",14);
342 vin->capability = V4L2_AUDCAP_STEREO;
343 ret = 0;
344 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300345 break;
346 }
347
348 case VIDIOC_G_AUDIO:
349 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300350 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
351 struct v4l2_audio *vin = arg;
352 memset(vin,0,sizeof(*vin));
353 vin->index = 0;
354 strncpy(vin->name, "PVRUSB2 Audio",14);
355 vin->capability = V4L2_AUDCAP_STEREO;
356 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300357 break;
358 }
359
360 case VIDIOC_S_AUDIO:
361 {
362 ret = -EINVAL;
363 break;
364 }
365 case VIDIOC_G_TUNER:
366 {
367 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300368
Michael Krufky8d364362007-01-22 02:17:55 -0300369 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300370
Mike Isely18103c52007-01-20 00:09:47 -0300371 pvr2_hdw_execute_tuner_poll(hdw);
372 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300373 break;
374 }
375
376 case VIDIOC_S_TUNER:
377 {
378 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
379
380 if (vt->index != 0)
381 break;
382
383 ret = pvr2_ctrl_set_value(
384 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
385 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300386 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300387 }
388
389 case VIDIOC_S_FREQUENCY:
390 {
391 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300392 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300393 struct v4l2_tuner vt;
394 int cur_input;
395 struct pvr2_ctrl *ctrlp;
396 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
397 if (ret != 0) break;
398 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
399 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
400 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300401 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300402 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
403 pvr2_ctrl_set_value(ctrlp,
404 PVR2_CVAL_INPUT_RADIO);
405 }
406 } else {
407 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
408 pvr2_ctrl_set_value(ctrlp,
409 PVR2_CVAL_INPUT_TV);
410 }
411 }
412 fv = vf->frequency;
413 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300414 fv = (fv * 125) / 2;
415 } else {
416 fv = fv * 62500;
417 }
Mike Iselyd8554972006-06-26 20:58:46 -0300418 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300419 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300420 break;
421 }
422
423 case VIDIOC_G_FREQUENCY:
424 {
425 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
426 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300427 int cur_input;
428 struct v4l2_tuner vt;
429 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
430 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300431 ret = pvr2_ctrl_get_value(
432 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
433 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300434 if (ret != 0) break;
435 pvr2_ctrl_get_value(
436 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
437 &cur_input);
438 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300439 vf->type = V4L2_TUNER_RADIO;
440 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300441 vf->type = V4L2_TUNER_ANALOG_TV;
442 }
Mike Isely18103c52007-01-20 00:09:47 -0300443 if (vt.capability & V4L2_TUNER_CAP_LOW) {
444 val = (val * 2) / 125;
445 } else {
446 val /= 62500;
447 }
448 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300449 break;
450 }
451
452 case VIDIOC_ENUM_FMT:
453 {
454 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
455
456 /* Only one format is supported : mpeg.*/
457 if (fd->index != 0)
458 break;
459
460 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
461 ret = 0;
462 break;
463 }
464
465 case VIDIOC_G_FMT:
466 {
467 struct v4l2_format *vf = (struct v4l2_format *)arg;
468 int val;
469 switch(vf->type) {
470 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
471 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
472 sizeof(struct v4l2_format));
473 val = 0;
474 pvr2_ctrl_get_value(
475 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
476 &val);
477 vf->fmt.pix.width = val;
478 val = 0;
479 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300480 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
481 &val);
482 vf->fmt.pix.height = val;
483 ret = 0;
484 break;
485 case V4L2_BUF_TYPE_VBI_CAPTURE:
486 // ????? Still need to figure out to do VBI correctly
487 ret = -EINVAL;
488 break;
489 default:
490 ret = -EINVAL;
491 break;
492 }
493 break;
494 }
495
496 case VIDIOC_TRY_FMT:
497 case VIDIOC_S_FMT:
498 {
499 struct v4l2_format *vf = (struct v4l2_format *)arg;
500
501 ret = 0;
502 switch(vf->type) {
503 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300504 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300505 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300506 int h = vf->fmt.pix.height;
507 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300508 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
509 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300510
Mike Iselye95a1912006-08-08 09:10:07 -0300511 lmin = pvr2_ctrl_get_min(hcp);
512 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300513 ldef = pvr2_ctrl_get_def(hcp);
514 if (w == -1) {
515 w = ldef;
516 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300517 w = lmin;
518 } else if (w > lmax) {
519 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300520 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300521 lmin = pvr2_ctrl_get_min(vcp);
522 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300523 ldef = pvr2_ctrl_get_def(vcp);
524 if (h == -1) {
525 h = ldef;
526 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300527 h = lmin;
528 } else if (h > lmax) {
529 h = lmax;
530 }
Mike Iselyd8554972006-06-26 20:58:46 -0300531
532 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
533 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300534 vf->fmt.pix.width = w;
535 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300536
537 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300538 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
539 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300540 }
541 } break;
542 case V4L2_BUF_TYPE_VBI_CAPTURE:
543 // ????? Still need to figure out to do VBI correctly
544 ret = -EINVAL;
545 break;
546 default:
547 ret = -EINVAL;
548 break;
549 }
550 break;
551 }
552
553 case VIDIOC_STREAMON:
554 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300555 if (!fh->dev_info->stream) {
556 /* No stream defined for this node. This means
557 that we're not currently allowed to stream from
558 this node. */
559 ret = -EPERM;
560 break;
561 }
Mike Iselyd8554972006-06-26 20:58:46 -0300562 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
563 if (ret < 0) return ret;
564 ret = pvr2_hdw_set_streaming(hdw,!0);
565 break;
566 }
567
568 case VIDIOC_STREAMOFF:
569 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300570 if (!fh->dev_info->stream) {
571 /* No stream defined for this node. This means
572 that we're not currently allowed to stream from
573 this node. */
574 ret = -EPERM;
575 break;
576 }
Mike Iselyd8554972006-06-26 20:58:46 -0300577 ret = pvr2_hdw_set_streaming(hdw,0);
578 break;
579 }
580
581 case VIDIOC_QUERYCTRL:
582 {
583 struct pvr2_ctrl *cptr;
584 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
585 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300586 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
587 cptr = pvr2_hdw_get_ctrl_nextv4l(
588 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
589 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
590 } else {
591 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
592 }
Mike Iselyd8554972006-06-26 20:58:46 -0300593 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300594 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300595 "QUERYCTRL id=0x%x not implemented here",
596 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300597 ret = -EINVAL;
598 break;
599 }
600
Mike Iselya761f432006-06-25 20:04:44 -0300601 pvr2_trace(PVR2_TRACE_V4LIOCTL,
602 "QUERYCTRL id=0x%x mapping name=%s (%s)",
603 vc->id,pvr2_ctrl_get_name(cptr),
604 pvr2_ctrl_get_desc(cptr));
605 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
606 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300607 vc->default_value = pvr2_ctrl_get_def(cptr);
608 switch (pvr2_ctrl_get_type(cptr)) {
609 case pvr2_ctl_enum:
610 vc->type = V4L2_CTRL_TYPE_MENU;
611 vc->minimum = 0;
612 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
613 vc->step = 1;
614 break;
Mike Isely33213962006-06-25 20:04:40 -0300615 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300616 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300617 vc->minimum = 0;
618 vc->maximum = 1;
619 vc->step = 1;
620 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300621 case pvr2_ctl_int:
622 vc->type = V4L2_CTRL_TYPE_INTEGER;
623 vc->minimum = pvr2_ctrl_get_min(cptr);
624 vc->maximum = pvr2_ctrl_get_max(cptr);
625 vc->step = 1;
626 break;
627 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300628 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300629 "QUERYCTRL id=0x%x name=%s not mappable",
630 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300631 ret = -EINVAL;
632 break;
633 }
634 break;
635 }
636
637 case VIDIOC_QUERYMENU:
638 {
639 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
640 unsigned int cnt = 0;
641 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
642 vm->index,
643 vm->name,sizeof(vm->name)-1,
644 &cnt);
645 vm->name[cnt] = 0;
646 break;
647 }
648
649 case VIDIOC_G_CTRL:
650 {
651 struct v4l2_control *vc = (struct v4l2_control *)arg;
652 int val = 0;
653 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
654 &val);
655 vc->value = val;
656 break;
657 }
658
659 case VIDIOC_S_CTRL:
660 {
661 struct v4l2_control *vc = (struct v4l2_control *)arg;
662 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
663 vc->value);
664 break;
665 }
666
Mike Isely1d9f8462006-06-25 20:04:58 -0300667 case VIDIOC_G_EXT_CTRLS:
668 {
669 struct v4l2_ext_controls *ctls =
670 (struct v4l2_ext_controls *)arg;
671 struct v4l2_ext_control *ctrl;
672 unsigned int idx;
673 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300674 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300675 for (idx = 0; idx < ctls->count; idx++) {
676 ctrl = ctls->controls + idx;
677 ret = pvr2_ctrl_get_value(
678 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
679 if (ret) {
680 ctls->error_idx = idx;
681 break;
682 }
683 /* Ensure that if read as a 64 bit value, the user
684 will still get a hopefully sane value */
685 ctrl->value64 = 0;
686 ctrl->value = val;
687 }
688 break;
689 }
690
691 case VIDIOC_S_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;
Mike Iselyc1c26802007-01-20 00:30:23 -0300697 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300698 for (idx = 0; idx < ctls->count; idx++) {
699 ctrl = ctls->controls + idx;
700 ret = pvr2_ctrl_set_value(
701 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
702 ctrl->value);
703 if (ret) {
704 ctls->error_idx = idx;
705 break;
706 }
707 }
708 break;
709 }
710
711 case VIDIOC_TRY_EXT_CTRLS:
712 {
713 struct v4l2_ext_controls *ctls =
714 (struct v4l2_ext_controls *)arg;
715 struct v4l2_ext_control *ctrl;
716 struct pvr2_ctrl *pctl;
717 unsigned int idx;
718 /* For the moment just validate that the requested control
719 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300720 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300721 for (idx = 0; idx < ctls->count; idx++) {
722 ctrl = ctls->controls + idx;
723 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
724 if (!pctl) {
725 ret = -EINVAL;
726 ctls->error_idx = idx;
727 break;
728 }
729 }
730 break;
731 }
732
Mike Iselyd8554972006-06-26 20:58:46 -0300733 case VIDIOC_LOG_STATUS:
734 {
Mike Iselyd8554972006-06-26 20:58:46 -0300735 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300736 ret = 0;
737 break;
738 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300739#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300740 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300741 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300742 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300743 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300744 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300745 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300746 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300747 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300748 cmd == VIDIOC_DBG_S_REGISTER,&val);
749 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300750 break;
751 }
752#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300753
754 default :
755 ret = v4l_compat_translate_ioctl(inode,file,cmd,
756 arg,pvr2_v4l2_do_ioctl);
757 }
758
759 pvr2_hdw_commit_ctl(hdw);
760
761 if (ret < 0) {
762 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300763 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300764 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
765 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300766 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
767 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300768 "pvr2_v4l2_do_ioctl failure, ret=%d"
769 " command was:",ret);
770 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
771 cmd);
772 }
773 }
774 } else {
775 pvr2_trace(PVR2_TRACE_V4LIOCTL,
776 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
777 ret,ret);
778 }
779 return ret;
780}
781
782
783static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
784{
Mike Isely0f0f2572006-12-27 23:19:42 -0300785 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300786 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300787 enum pvr2_config cfg = dip->config;
788 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300789
Mike Isely16eb40d2006-12-30 18:27:32 -0300790 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300791
792 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300793 dip->v4lp = NULL;
794 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300795
796 /* Actual deallocation happens later when all internal references
797 are gone. */
798 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300799
Mike Isely16eb40d2006-12-30 18:27:32 -0300800 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
801 get_v4l_name(v4l_type),minor_id & 0x1f,
802 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300803
Mike Iselyd8554972006-06-26 20:58:46 -0300804}
805
806
807static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
808{
Mike Isely0f0f2572006-12-27 23:19:42 -0300809 if (vp->dev_video) {
810 pvr2_v4l2_dev_destroy(vp->dev_video);
811 vp->dev_video = 0;
812 }
813 if (vp->dev_radio) {
814 pvr2_v4l2_dev_destroy(vp->dev_radio);
815 vp->dev_radio = 0;
816 }
Mike Iselyd8554972006-06-26 20:58:46 -0300817
818 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
819 pvr2_channel_done(&vp->channel);
820 kfree(vp);
821}
822
823
Mike Isely75910052006-09-23 22:30:50 -0300824static void pvr2_video_device_release(struct video_device *vdev)
825{
826 struct pvr2_v4l2_dev *dev;
827 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
828 kfree(dev);
829}
830
831
Adrian Bunk07e337e2006-06-30 11:30:20 -0300832static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300833{
834 struct pvr2_v4l2 *vp;
835 vp = container_of(chp,struct pvr2_v4l2,channel);
836 if (!vp->channel.mc_head->disconnect_flag) return;
837 if (vp->vfirst) return;
838 pvr2_v4l2_destroy_no_lock(vp);
839}
840
841
Adrian Bunk07e337e2006-06-30 11:30:20 -0300842static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
843 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300844{
845
846/* Temporary hack : use ivtv api until a v4l2 one is available. */
847#define IVTV_IOC_G_CODEC 0xFFEE7703
848#define IVTV_IOC_S_CODEC 0xFFEE7704
849 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
850 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
851}
852
853
Adrian Bunk07e337e2006-06-30 11:30:20 -0300854static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300855{
856 struct pvr2_v4l2_fh *fhp = file->private_data;
857 struct pvr2_v4l2 *vp = fhp->vhead;
858 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300859 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300860
861 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
862
863 if (fhp->rhp) {
864 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300865 pvr2_hdw_set_streaming(hdw,0);
866 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300867 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300868 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300869 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300870 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300871
Mike Iselyd8554972006-06-26 20:58:46 -0300872 v4l2_prio_close(&vp->prio, &fhp->prio);
873 file->private_data = NULL;
874
875 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300876 /* Restore the previous input selection, if it makes sense
877 to do so. */
878 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
879 struct pvr2_ctrl *cp;
880 int pval;
881 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
882 pvr2_ctrl_get_value(cp,&pval);
883 /* Only restore if we're still selecting the radio */
884 if (pval == PVR2_CVAL_INPUT_RADIO) {
885 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
886 pvr2_hdw_commit_ctl(hdw);
887 }
888 }
889
Mike Iselyd8554972006-06-26 20:58:46 -0300890 if (fhp->vnext) {
891 fhp->vnext->vprev = fhp->vprev;
892 } else {
893 vp->vlast = fhp->vprev;
894 }
895 if (fhp->vprev) {
896 fhp->vprev->vnext = fhp->vnext;
897 } else {
898 vp->vfirst = fhp->vnext;
899 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300900 fhp->vnext = NULL;
901 fhp->vprev = NULL;
902 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300903 pvr2_channel_done(&fhp->channel);
904 pvr2_trace(PVR2_TRACE_STRUCT,
905 "Destroying pvr_v4l2_fh id=%p",fhp);
906 kfree(fhp);
907 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
908 pvr2_v4l2_destroy_no_lock(vp);
909 }
910 } while (0); pvr2_context_exit(mp);
911 return 0;
912}
913
914
Adrian Bunk07e337e2006-06-30 11:30:20 -0300915static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300916{
Mike Isely75910052006-09-23 22:30:50 -0300917 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300918 struct pvr2_v4l2_fh *fhp;
919 struct pvr2_v4l2 *vp;
920 struct pvr2_hdw *hdw;
921
Mike Isely75910052006-09-23 22:30:50 -0300922 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300923
924 vp = dip->v4lp;
925 hdw = vp->channel.hdw;
926
927 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
928
929 if (!pvr2_hdw_dev_ok(hdw)) {
930 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
931 "pvr2_v4l2_open: hardware not ready");
932 return -EIO;
933 }
934
Mike Isely4b85dee2007-01-20 00:03:32 -0300935 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300936 if (!fhp) {
937 return -ENOMEM;
938 }
Mike Iselyd8554972006-06-26 20:58:46 -0300939
940 init_waitqueue_head(&fhp->wait_data);
941 fhp->dev_info = dip;
942
943 pvr2_context_enter(vp->channel.mc_head); do {
944 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
945 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300946
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300947 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300948 fhp->vprev = vp->vlast;
949 if (vp->vlast) {
950 vp->vlast->vnext = fhp;
951 } else {
952 vp->vfirst = fhp;
953 }
954 vp->vlast = fhp;
955 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300956
957 /* Opening the /dev/radioX device implies a mode switch.
958 So execute that here. Note that you can get the
959 IDENTICAL effect merely by opening the normal video
960 device and setting the input appropriately. */
961 if (dip->v4l_type == VFL_TYPE_RADIO) {
962 struct pvr2_ctrl *cp;
963 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
964 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
965 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
966 pvr2_hdw_commit_ctl(hdw);
967 }
Mike Iselyd8554972006-06-26 20:58:46 -0300968 } while (0); pvr2_context_exit(vp->channel.mc_head);
969
970 fhp->file = file;
971 file->private_data = fhp;
972 v4l2_prio_open(&vp->prio,&fhp->prio);
973
974 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
975
976 return 0;
977}
978
979
980static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
981{
982 wake_up(&fhp->wait_data);
983}
984
985static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
986{
987 int ret;
988 struct pvr2_stream *sp;
989 struct pvr2_hdw *hdw;
990 if (fh->rhp) return 0;
991
Mike Isely16eb40d2006-12-30 18:27:32 -0300992 if (!fh->dev_info->stream) {
993 /* No stream defined for this node. This means that we're
994 not currently allowed to stream from this node. */
995 return -EPERM;
996 }
997
Mike Iselyd8554972006-06-26 20:58:46 -0300998 /* First read() attempt. Try to claim the stream and start
999 it... */
1000 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1001 fh->dev_info->stream)) != 0) {
1002 /* Someone else must already have it */
1003 return ret;
1004 }
1005
1006 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1007 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001008 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001009 return -ENOMEM;
1010 }
1011
1012 hdw = fh->channel.mc_head->hdw;
1013 sp = fh->dev_info->stream->stream;
1014 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1015 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
1016 pvr2_hdw_set_streaming(hdw,!0);
1017 ret = pvr2_ioread_set_enabled(fh->rhp,!0);
1018
1019 return ret;
1020}
1021
1022
1023static ssize_t pvr2_v4l2_read(struct file *file,
1024 char __user *buff, size_t count, loff_t *ppos)
1025{
1026 struct pvr2_v4l2_fh *fh = file->private_data;
1027 int ret;
1028
1029 if (fh->fw_mode_flag) {
1030 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1031 char *tbuf;
1032 int c1,c2;
1033 int tcnt = 0;
1034 unsigned int offs = *ppos;
1035
1036 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1037 if (!tbuf) return -ENOMEM;
1038
1039 while (count) {
1040 c1 = count;
1041 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1042 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1043 if (c2 < 0) {
1044 tcnt = c2;
1045 break;
1046 }
1047 if (!c2) break;
1048 if (copy_to_user(buff,tbuf,c2)) {
1049 tcnt = -EFAULT;
1050 break;
1051 }
1052 offs += c2;
1053 tcnt += c2;
1054 buff += c2;
1055 count -= c2;
1056 *ppos += c2;
1057 }
1058 kfree(tbuf);
1059 return tcnt;
1060 }
1061
1062 if (!fh->rhp) {
1063 ret = pvr2_v4l2_iosetup(fh);
1064 if (ret) {
1065 return ret;
1066 }
1067 }
1068
1069 for (;;) {
1070 ret = pvr2_ioread_read(fh->rhp,buff,count);
1071 if (ret >= 0) break;
1072 if (ret != -EAGAIN) break;
1073 if (file->f_flags & O_NONBLOCK) break;
1074 /* Doing blocking I/O. Wait here. */
1075 ret = wait_event_interruptible(
1076 fh->wait_data,
1077 pvr2_ioread_avail(fh->rhp) >= 0);
1078 if (ret < 0) break;
1079 }
1080
1081 return ret;
1082}
1083
1084
1085static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1086{
1087 unsigned int mask = 0;
1088 struct pvr2_v4l2_fh *fh = file->private_data;
1089 int ret;
1090
1091 if (fh->fw_mode_flag) {
1092 mask |= POLLIN | POLLRDNORM;
1093 return mask;
1094 }
1095
1096 if (!fh->rhp) {
1097 ret = pvr2_v4l2_iosetup(fh);
1098 if (ret) return POLLERR;
1099 }
1100
1101 poll_wait(file,&fh->wait_data,wait);
1102
1103 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1104 mask |= POLLIN | POLLRDNORM;
1105 }
1106
1107 return mask;
1108}
1109
1110
Arjan van de Venfa027c22007-02-12 00:55:33 -08001111static const struct file_operations vdev_fops = {
Mike Iselyd8554972006-06-26 20:58:46 -03001112 .owner = THIS_MODULE,
1113 .open = pvr2_v4l2_open,
1114 .release = pvr2_v4l2_release,
1115 .read = pvr2_v4l2_read,
1116 .ioctl = pvr2_v4l2_ioctl,
1117 .llseek = no_llseek,
1118 .poll = pvr2_v4l2_poll,
1119};
1120
1121
1122#define VID_HARDWARE_PVRUSB2 38 /* FIXME : need a good value */
1123
1124static struct video_device vdev_template = {
1125 .owner = THIS_MODULE,
1126 .type = VID_TYPE_CAPTURE | VID_TYPE_TUNER,
1127 .type2 = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE
1128 | V4L2_CAP_TUNER | V4L2_CAP_AUDIO
1129 | V4L2_CAP_READWRITE),
1130 .hardware = VID_HARDWARE_PVRUSB2,
1131 .fops = &vdev_fops,
1132};
1133
1134
1135static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1136 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001137 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001138{
1139 int mindevnum;
1140 int unit_number;
Mike Isely16eb40d2006-12-30 18:27:32 -03001141 int *nr_ptr = 0;
Mike Iselyd8554972006-06-26 20:58:46 -03001142 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001143
1144
Mike Isely16eb40d2006-12-30 18:27:32 -03001145 dip->v4l_type = v4l_type;
1146 switch (v4l_type) {
1147 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001148 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001149 dip->config = pvr2_config_mpeg;
1150 dip->minor_type = pvr2_v4l_type_video;
1151 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001152 if (!dip->stream) {
1153 err("Failed to set up pvrusb2 v4l video dev"
1154 " due to missing stream instance");
1155 return;
1156 }
Mike Iselyd8554972006-06-26 20:58:46 -03001157 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001158 case VFL_TYPE_VBI:
1159 dip->config = pvr2_config_vbi;
1160 dip->minor_type = pvr2_v4l_type_vbi;
1161 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001162 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001163 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001164 dip->stream = &vp->channel.mc_head->video_stream;
1165 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001166 dip->minor_type = pvr2_v4l_type_radio;
1167 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001168 break;
1169 default:
1170 /* Bail out (this should be impossible) */
1171 err("Failed to set up pvrusb2 v4l dev"
1172 " due to unrecognized config");
1173 return;
1174 }
1175
Mike Isely75910052006-09-23 22:30:50 -03001176 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1177 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001178
1179 mindevnum = -1;
1180 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001181 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1182 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001183 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001184 if ((video_register_device(&dip->devbase,
1185 dip->v4l_type, mindevnum) < 0) &&
1186 (video_register_device(&dip->devbase,
1187 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001188 err("Failed to register pvrusb2 v4l device");
1189 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001190
1191 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1192 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1193 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001194
Mike Iselyd8554972006-06-26 20:58:46 -03001195 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001196 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001197}
1198
1199
1200struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1201{
1202 struct pvr2_v4l2 *vp;
1203
Mike Isely4b85dee2007-01-20 00:03:32 -03001204 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001205 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001206 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1207 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f2572006-12-27 23:19:42 -03001208 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001209 kfree(vp->dev_video);
1210 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001211 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001212 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001213 }
Mike Iselyd8554972006-06-26 20:58:46 -03001214 pvr2_channel_init(&vp->channel,mnp);
1215 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1216
1217 vp->channel.check_func = pvr2_v4l2_internal_check;
1218
1219 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001220 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1221 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001222
1223 return vp;
1224}
1225
1226/*
1227 Stuff for Emacs to see, in order to encourage consistent editing style:
1228 *** Local Variables: ***
1229 *** mode: c ***
1230 *** fill-column: 75 ***
1231 *** tab-width: 8 ***
1232 *** c-basic-offset: 8 ***
1233 *** End: ***
1234 */