blob: 5e2292726e945589c6d2e19a86c41b4781efd807 [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));
Mike Isely31a18542007-04-08 01:11:47 -0300206 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
207 sizeof(cap->bus_info));
Mike Isely78a47102007-11-26 01:58:20 -0300208 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
Mike Iselyd8554972006-06-26 20:58:46 -0300209
210 ret = 0;
211 break;
212 }
213
214 case VIDIOC_G_PRIORITY:
215 {
216 enum v4l2_priority *p = arg;
217
218 *p = v4l2_prio_max(&vp->prio);
219 ret = 0;
220 break;
221 }
222
223 case VIDIOC_S_PRIORITY:
224 {
225 enum v4l2_priority *prio = arg;
226
227 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
228 break;
229 }
230
231 case VIDIOC_ENUMSTD:
232 {
233 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
234 int idx = vs->index;
235 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
236 break;
237 }
238
239 case VIDIOC_G_STD:
240 {
241 int val = 0;
242 ret = pvr2_ctrl_get_value(
243 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
244 *(v4l2_std_id *)arg = val;
245 break;
246 }
247
248 case VIDIOC_S_STD:
249 {
250 ret = pvr2_ctrl_set_value(
251 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
252 *(v4l2_std_id *)arg);
253 break;
254 }
255
256 case VIDIOC_ENUMINPUT:
257 {
258 struct pvr2_ctrl *cptr;
259 struct v4l2_input *vi = (struct v4l2_input *)arg;
260 struct v4l2_input tmp;
261 unsigned int cnt;
262
263 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
264
265 memset(&tmp,0,sizeof(tmp));
266 tmp.index = vi->index;
267 ret = 0;
268 switch (vi->index) {
269 case PVR2_CVAL_INPUT_TV:
Mike Isely895c3e82008-04-22 14:45:37 -0300270 case PVR2_CVAL_INPUT_DTV:
Mike Iselyd8554972006-06-26 20:58:46 -0300271 case PVR2_CVAL_INPUT_RADIO:
272 tmp.type = V4L2_INPUT_TYPE_TUNER;
273 break;
274 case PVR2_CVAL_INPUT_SVIDEO:
275 case PVR2_CVAL_INPUT_COMPOSITE:
276 tmp.type = V4L2_INPUT_TYPE_CAMERA;
277 break;
278 default:
279 ret = -EINVAL;
280 break;
281 }
282 if (ret < 0) break;
283
284 cnt = 0;
285 pvr2_ctrl_get_valname(cptr,vi->index,
286 tmp.name,sizeof(tmp.name)-1,&cnt);
287 tmp.name[cnt] = 0;
288
289 /* Don't bother with audioset, since this driver currently
290 always switches the audio whenever the video is
291 switched. */
292
293 /* Handling std is a tougher problem. It doesn't make
294 sense in cases where a device might be multi-standard.
295 We could just copy out the current value for the
296 standard, but it can change over time. For now just
297 leave it zero. */
298
299 memcpy(vi, &tmp, sizeof(tmp));
300
301 ret = 0;
302 break;
303 }
304
305 case VIDIOC_G_INPUT:
306 {
307 struct pvr2_ctrl *cptr;
308 struct v4l2_input *vi = (struct v4l2_input *)arg;
309 int val;
310 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
311 val = 0;
312 ret = pvr2_ctrl_get_value(cptr,&val);
313 vi->index = val;
314 break;
315 }
316
317 case VIDIOC_S_INPUT:
318 {
319 struct v4l2_input *vi = (struct v4l2_input *)arg;
320 ret = pvr2_ctrl_set_value(
321 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
322 vi->index);
323 break;
324 }
325
326 case VIDIOC_ENUMAUDIO:
327 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300328 /* pkt: FIXME: We are returning one "fake" input here
329 which could very well be called "whatever_we_like".
330 This is for apps that want to see an audio input
331 just to feel comfortable, as well as to test if
332 it can do stereo or sth. There is actually no guarantee
333 that the actual audio input cannot change behind the app's
334 back, but most applications should not mind that either.
335
336 Hopefully, mplayer people will work with us on this (this
337 whole mess is to support mplayer pvr://), or Hans will come
338 up with a more standard way to say "we have inputs but we
339 don 't want you to change them independent of video" which
340 will sort this mess.
341 */
342 struct v4l2_audio *vin = arg;
Mike Iselyd8554972006-06-26 20:58:46 -0300343 ret = -EINVAL;
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300344 if (vin->index > 0) break;
345 strncpy(vin->name, "PVRUSB2 Audio",14);
346 vin->capability = V4L2_AUDCAP_STEREO;
347 ret = 0;
348 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300349 break;
350 }
351
352 case VIDIOC_G_AUDIO:
353 {
Pantelis Koukousoulas848ed3c2007-01-20 01:57:36 -0300354 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
355 struct v4l2_audio *vin = arg;
356 memset(vin,0,sizeof(*vin));
357 vin->index = 0;
358 strncpy(vin->name, "PVRUSB2 Audio",14);
359 vin->capability = V4L2_AUDCAP_STEREO;
360 ret = 0;
Mike Iselyd8554972006-06-26 20:58:46 -0300361 break;
362 }
363
364 case VIDIOC_S_AUDIO:
365 {
366 ret = -EINVAL;
367 break;
368 }
369 case VIDIOC_G_TUNER:
370 {
371 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300372
Michael Krufky8d364362007-01-22 02:17:55 -0300373 if (vt->index != 0) break; /* Only answer for the 1st tuner */
Mauro Carvalho Chehab5cc1dd82007-01-21 22:02:58 -0300374
Mike Isely18103c52007-01-20 00:09:47 -0300375 pvr2_hdw_execute_tuner_poll(hdw);
376 ret = pvr2_hdw_get_tuner_status(hdw,vt);
Mike Iselyd8554972006-06-26 20:58:46 -0300377 break;
378 }
379
380 case VIDIOC_S_TUNER:
381 {
382 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
383
384 if (vt->index != 0)
385 break;
386
387 ret = pvr2_ctrl_set_value(
388 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
389 vt->audmode);
Mike Isely11fc76c2007-01-20 00:24:52 -0300390 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300391 }
392
393 case VIDIOC_S_FREQUENCY:
394 {
395 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
Mike Iselyc0e69312006-12-27 23:25:06 -0300396 unsigned long fv;
Mike Isely18103c52007-01-20 00:09:47 -0300397 struct v4l2_tuner vt;
398 int cur_input;
399 struct pvr2_ctrl *ctrlp;
400 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
401 if (ret != 0) break;
402 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
403 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
404 if (ret != 0) break;
Mike Iselyc0e69312006-12-27 23:25:06 -0300405 if (vf->type == V4L2_TUNER_RADIO) {
Mike Isely18103c52007-01-20 00:09:47 -0300406 if (cur_input != PVR2_CVAL_INPUT_RADIO) {
407 pvr2_ctrl_set_value(ctrlp,
408 PVR2_CVAL_INPUT_RADIO);
409 }
410 } else {
411 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
412 pvr2_ctrl_set_value(ctrlp,
413 PVR2_CVAL_INPUT_TV);
414 }
415 }
416 fv = vf->frequency;
417 if (vt.capability & V4L2_TUNER_CAP_LOW) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300418 fv = (fv * 125) / 2;
419 } else {
420 fv = fv * 62500;
421 }
Mike Iselyd8554972006-06-26 20:58:46 -0300422 ret = pvr2_ctrl_set_value(
Mike Iselyc0e69312006-12-27 23:25:06 -0300423 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
Mike Iselyd8554972006-06-26 20:58:46 -0300424 break;
425 }
426
427 case VIDIOC_G_FREQUENCY:
428 {
429 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
430 int val = 0;
Mike Isely18103c52007-01-20 00:09:47 -0300431 int cur_input;
432 struct v4l2_tuner vt;
433 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
434 if (ret != 0) break;
Mike Iselyd8554972006-06-26 20:58:46 -0300435 ret = pvr2_ctrl_get_value(
436 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
437 &val);
Mike Iselyc0e69312006-12-27 23:25:06 -0300438 if (ret != 0) break;
439 pvr2_ctrl_get_value(
440 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
441 &cur_input);
442 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
Mike Iselyc0e69312006-12-27 23:25:06 -0300443 vf->type = V4L2_TUNER_RADIO;
444 } else {
Mike Iselyc0e69312006-12-27 23:25:06 -0300445 vf->type = V4L2_TUNER_ANALOG_TV;
446 }
Mike Isely18103c52007-01-20 00:09:47 -0300447 if (vt.capability & V4L2_TUNER_CAP_LOW) {
448 val = (val * 2) / 125;
449 } else {
450 val /= 62500;
451 }
452 vf->frequency = val;
Mike Iselyd8554972006-06-26 20:58:46 -0300453 break;
454 }
455
456 case VIDIOC_ENUM_FMT:
457 {
458 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
459
460 /* Only one format is supported : mpeg.*/
461 if (fd->index != 0)
462 break;
463
464 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
465 ret = 0;
466 break;
467 }
468
469 case VIDIOC_G_FMT:
470 {
471 struct v4l2_format *vf = (struct v4l2_format *)arg;
472 int val;
473 switch(vf->type) {
474 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
475 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
476 sizeof(struct v4l2_format));
477 val = 0;
478 pvr2_ctrl_get_value(
479 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
480 &val);
481 vf->fmt.pix.width = val;
482 val = 0;
483 pvr2_ctrl_get_value(
Mike Iselyd8554972006-06-26 20:58:46 -0300484 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
485 &val);
486 vf->fmt.pix.height = val;
487 ret = 0;
488 break;
489 case V4L2_BUF_TYPE_VBI_CAPTURE:
490 // ????? Still need to figure out to do VBI correctly
491 ret = -EINVAL;
492 break;
493 default:
494 ret = -EINVAL;
495 break;
496 }
497 break;
498 }
499
500 case VIDIOC_TRY_FMT:
501 case VIDIOC_S_FMT:
502 {
503 struct v4l2_format *vf = (struct v4l2_format *)arg;
504
505 ret = 0;
506 switch(vf->type) {
507 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300508 int lmin,lmax,ldef;
Mike Iselye95a1912006-08-08 09:10:07 -0300509 struct pvr2_ctrl *hcp,*vcp;
Mike Iselyd8554972006-06-26 20:58:46 -0300510 int h = vf->fmt.pix.height;
511 int w = vf->fmt.pix.width;
Mike Iselye95a1912006-08-08 09:10:07 -0300512 hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
513 vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
Mike Iselyd8554972006-06-26 20:58:46 -0300514
Mike Iselye95a1912006-08-08 09:10:07 -0300515 lmin = pvr2_ctrl_get_min(hcp);
516 lmax = pvr2_ctrl_get_max(hcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300517 ldef = pvr2_ctrl_get_def(hcp);
518 if (w == -1) {
519 w = ldef;
520 } else if (w < lmin) {
Mike Iselye95a1912006-08-08 09:10:07 -0300521 w = lmin;
522 } else if (w > lmax) {
523 w = lmax;
Mike Isely039c4302006-06-25 20:04:16 -0300524 }
Hans Verkuilb31e3412006-09-01 18:36:10 -0300525 lmin = pvr2_ctrl_get_min(vcp);
526 lmax = pvr2_ctrl_get_max(vcp);
Pantelis Koukousoulasfd694962007-01-20 01:59:54 -0300527 ldef = pvr2_ctrl_get_def(vcp);
528 if (h == -1) {
529 h = ldef;
530 } else if (h < lmin) {
Hans Verkuilb31e3412006-09-01 18:36:10 -0300531 h = lmin;
532 } else if (h > lmax) {
533 h = lmax;
534 }
Mike Iselyd8554972006-06-26 20:58:46 -0300535
536 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
537 sizeof(struct v4l2_format));
Mike Isely039c4302006-06-25 20:04:16 -0300538 vf->fmt.pix.width = w;
539 vf->fmt.pix.height = h;
Mike Iselyd8554972006-06-26 20:58:46 -0300540
541 if (cmd == VIDIOC_S_FMT) {
Mike Iselye95a1912006-08-08 09:10:07 -0300542 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
543 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
Mike Iselyd8554972006-06-26 20:58:46 -0300544 }
545 } break;
546 case V4L2_BUF_TYPE_VBI_CAPTURE:
547 // ????? Still need to figure out to do VBI correctly
548 ret = -EINVAL;
549 break;
550 default:
551 ret = -EINVAL;
552 break;
553 }
554 break;
555 }
556
557 case VIDIOC_STREAMON:
558 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300559 if (!fh->dev_info->stream) {
560 /* No stream defined for this node. This means
561 that we're not currently allowed to stream from
562 this node. */
563 ret = -EPERM;
564 break;
565 }
Mike Iselyd8554972006-06-26 20:58:46 -0300566 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
567 if (ret < 0) return ret;
568 ret = pvr2_hdw_set_streaming(hdw,!0);
569 break;
570 }
571
572 case VIDIOC_STREAMOFF:
573 {
Mike Isely16eb40d2006-12-30 18:27:32 -0300574 if (!fh->dev_info->stream) {
575 /* No stream defined for this node. This means
576 that we're not currently allowed to stream from
577 this node. */
578 ret = -EPERM;
579 break;
580 }
Mike Iselyd8554972006-06-26 20:58:46 -0300581 ret = pvr2_hdw_set_streaming(hdw,0);
582 break;
583 }
584
585 case VIDIOC_QUERYCTRL:
586 {
587 struct pvr2_ctrl *cptr;
588 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
589 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300590 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
591 cptr = pvr2_hdw_get_ctrl_nextv4l(
592 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
593 if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
594 } else {
595 cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
596 }
Mike Iselyd8554972006-06-26 20:58:46 -0300597 if (!cptr) {
Mike Isely0885ba12006-06-25 21:30:47 -0300598 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300599 "QUERYCTRL id=0x%x not implemented here",
600 vc->id);
Mike Iselyd8554972006-06-26 20:58:46 -0300601 ret = -EINVAL;
602 break;
603 }
604
Mike Iselya761f432006-06-25 20:04:44 -0300605 pvr2_trace(PVR2_TRACE_V4LIOCTL,
606 "QUERYCTRL id=0x%x mapping name=%s (%s)",
607 vc->id,pvr2_ctrl_get_name(cptr),
608 pvr2_ctrl_get_desc(cptr));
609 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
610 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
Mike Iselyd8554972006-06-26 20:58:46 -0300611 vc->default_value = pvr2_ctrl_get_def(cptr);
612 switch (pvr2_ctrl_get_type(cptr)) {
613 case pvr2_ctl_enum:
614 vc->type = V4L2_CTRL_TYPE_MENU;
615 vc->minimum = 0;
616 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
617 vc->step = 1;
618 break;
Mike Isely33213962006-06-25 20:04:40 -0300619 case pvr2_ctl_bool:
Mike Isely1d9f8462006-06-25 20:04:58 -0300620 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
Mike Isely33213962006-06-25 20:04:40 -0300621 vc->minimum = 0;
622 vc->maximum = 1;
623 vc->step = 1;
624 break;
Mike Iselyd8554972006-06-26 20:58:46 -0300625 case pvr2_ctl_int:
626 vc->type = V4L2_CTRL_TYPE_INTEGER;
627 vc->minimum = pvr2_ctrl_get_min(cptr);
628 vc->maximum = pvr2_ctrl_get_max(cptr);
629 vc->step = 1;
630 break;
631 default:
Mike Isely0885ba12006-06-25 21:30:47 -0300632 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselya761f432006-06-25 20:04:44 -0300633 "QUERYCTRL id=0x%x name=%s not mappable",
634 vc->id,pvr2_ctrl_get_name(cptr));
Mike Iselyd8554972006-06-26 20:58:46 -0300635 ret = -EINVAL;
636 break;
637 }
638 break;
639 }
640
641 case VIDIOC_QUERYMENU:
642 {
643 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
644 unsigned int cnt = 0;
645 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
646 vm->index,
647 vm->name,sizeof(vm->name)-1,
648 &cnt);
649 vm->name[cnt] = 0;
650 break;
651 }
652
653 case VIDIOC_G_CTRL:
654 {
655 struct v4l2_control *vc = (struct v4l2_control *)arg;
656 int val = 0;
657 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
658 &val);
659 vc->value = val;
660 break;
661 }
662
663 case VIDIOC_S_CTRL:
664 {
665 struct v4l2_control *vc = (struct v4l2_control *)arg;
666 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
667 vc->value);
668 break;
669 }
670
Mike Isely1d9f8462006-06-25 20:04:58 -0300671 case VIDIOC_G_EXT_CTRLS:
672 {
673 struct v4l2_ext_controls *ctls =
674 (struct v4l2_ext_controls *)arg;
675 struct v4l2_ext_control *ctrl;
676 unsigned int idx;
677 int val;
Mike Iselyc1c26802007-01-20 00:30:23 -0300678 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300679 for (idx = 0; idx < ctls->count; idx++) {
680 ctrl = ctls->controls + idx;
681 ret = pvr2_ctrl_get_value(
682 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
683 if (ret) {
684 ctls->error_idx = idx;
685 break;
686 }
687 /* Ensure that if read as a 64 bit value, the user
688 will still get a hopefully sane value */
689 ctrl->value64 = 0;
690 ctrl->value = val;
691 }
692 break;
693 }
694
695 case VIDIOC_S_EXT_CTRLS:
696 {
697 struct v4l2_ext_controls *ctls =
698 (struct v4l2_ext_controls *)arg;
699 struct v4l2_ext_control *ctrl;
700 unsigned int idx;
Mike Iselyc1c26802007-01-20 00:30:23 -0300701 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300702 for (idx = 0; idx < ctls->count; idx++) {
703 ctrl = ctls->controls + idx;
704 ret = pvr2_ctrl_set_value(
705 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
706 ctrl->value);
707 if (ret) {
708 ctls->error_idx = idx;
709 break;
710 }
711 }
712 break;
713 }
714
715 case VIDIOC_TRY_EXT_CTRLS:
716 {
717 struct v4l2_ext_controls *ctls =
718 (struct v4l2_ext_controls *)arg;
719 struct v4l2_ext_control *ctrl;
720 struct pvr2_ctrl *pctl;
721 unsigned int idx;
722 /* For the moment just validate that the requested control
723 actually exists. */
Mike Iselyc1c26802007-01-20 00:30:23 -0300724 ret = 0;
Mike Isely1d9f8462006-06-25 20:04:58 -0300725 for (idx = 0; idx < ctls->count; idx++) {
726 ctrl = ctls->controls + idx;
727 pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
728 if (!pctl) {
729 ret = -EINVAL;
730 ctls->error_idx = idx;
731 break;
732 }
733 }
734 break;
735 }
736
Mike Iselyd8554972006-06-26 20:58:46 -0300737 case VIDIOC_LOG_STATUS:
738 {
Mike Iselyd8554972006-06-26 20:58:46 -0300739 pvr2_hdw_trigger_module_log(hdw);
Mike Iselyd8554972006-06-26 20:58:46 -0300740 ret = 0;
741 break;
742 }
Mike Isely32ffa9a2006-09-23 22:26:52 -0300743#ifdef CONFIG_VIDEO_ADV_DEBUG
Trent Piepho52ebc762007-01-23 22:38:13 -0300744 case VIDIOC_DBG_S_REGISTER:
Trent Piepho52ebc762007-01-23 22:38:13 -0300745 case VIDIOC_DBG_G_REGISTER:
Mike Isely32ffa9a2006-09-23 22:26:52 -0300746 {
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300747 u64 val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300748 struct v4l2_register *req = (struct v4l2_register *)arg;
Trent Piepho52ebc762007-01-23 22:38:13 -0300749 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300750 ret = pvr2_hdw_register_access(
Hans Verkuilf3d092b2007-02-23 20:55:14 -0300751 hdw,req->match_type,req->match_chip,req->reg,
Trent Piepho52ebc762007-01-23 22:38:13 -0300752 cmd == VIDIOC_DBG_S_REGISTER,&val);
753 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
Mike Isely32ffa9a2006-09-23 22:26:52 -0300754 break;
755 }
756#endif
Mike Iselyd8554972006-06-26 20:58:46 -0300757
758 default :
759 ret = v4l_compat_translate_ioctl(inode,file,cmd,
760 arg,pvr2_v4l2_do_ioctl);
761 }
762
763 pvr2_hdw_commit_ctl(hdw);
764
765 if (ret < 0) {
766 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
Mike Isely0885ba12006-06-25 21:30:47 -0300767 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300768 "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
769 } else {
Mike Isely0885ba12006-06-25 21:30:47 -0300770 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
771 pvr2_trace(PVR2_TRACE_V4LIOCTL,
Mike Iselyd8554972006-06-26 20:58:46 -0300772 "pvr2_v4l2_do_ioctl failure, ret=%d"
773 " command was:",ret);
774 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
775 cmd);
776 }
777 }
778 } else {
779 pvr2_trace(PVR2_TRACE_V4LIOCTL,
780 "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
781 ret,ret);
782 }
783 return ret;
784}
785
786
787static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
788{
Mike Isely0f0f2572006-12-27 23:19:42 -0300789 int minor_id = dip->devbase.minor;
Mike Isely0f0f2572006-12-27 23:19:42 -0300790 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
Mike Isely16eb40d2006-12-30 18:27:32 -0300791 enum pvr2_config cfg = dip->config;
792 int v4l_type = dip->v4l_type;
Mike Isely0f0f2572006-12-27 23:19:42 -0300793
Mike Isely16eb40d2006-12-30 18:27:32 -0300794 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
Mike Isely75910052006-09-23 22:30:50 -0300795
796 /* Paranoia */
Randy Dunlapc2625bf2006-10-29 11:12:27 -0300797 dip->v4lp = NULL;
798 dip->stream = NULL;
Mike Isely75910052006-09-23 22:30:50 -0300799
800 /* Actual deallocation happens later when all internal references
801 are gone. */
802 video_unregister_device(&dip->devbase);
Mike Isely0f0f2572006-12-27 23:19:42 -0300803
Mike Isely16eb40d2006-12-30 18:27:32 -0300804 printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
805 get_v4l_name(v4l_type),minor_id & 0x1f,
806 pvr2_config_get_name(cfg));
Mike Isely0f0f2572006-12-27 23:19:42 -0300807
Mike Iselyd8554972006-06-26 20:58:46 -0300808}
809
810
811static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
812{
Mike Isely0f0f2572006-12-27 23:19:42 -0300813 if (vp->dev_video) {
814 pvr2_v4l2_dev_destroy(vp->dev_video);
Al Viro89952d12007-03-14 09:17:59 +0000815 vp->dev_video = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300816 }
817 if (vp->dev_radio) {
818 pvr2_v4l2_dev_destroy(vp->dev_radio);
Al Viro89952d12007-03-14 09:17:59 +0000819 vp->dev_radio = NULL;
Mike Isely0f0f2572006-12-27 23:19:42 -0300820 }
Mike Iselyd8554972006-06-26 20:58:46 -0300821
822 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
823 pvr2_channel_done(&vp->channel);
824 kfree(vp);
825}
826
827
Mike Isely75910052006-09-23 22:30:50 -0300828static void pvr2_video_device_release(struct video_device *vdev)
829{
830 struct pvr2_v4l2_dev *dev;
831 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
832 kfree(dev);
833}
834
835
Adrian Bunk07e337e2006-06-30 11:30:20 -0300836static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
Mike Iselyd8554972006-06-26 20:58:46 -0300837{
838 struct pvr2_v4l2 *vp;
839 vp = container_of(chp,struct pvr2_v4l2,channel);
840 if (!vp->channel.mc_head->disconnect_flag) return;
841 if (vp->vfirst) return;
842 pvr2_v4l2_destroy_no_lock(vp);
843}
844
845
Adrian Bunk07e337e2006-06-30 11:30:20 -0300846static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
847 unsigned int cmd, unsigned long arg)
Mike Iselyd8554972006-06-26 20:58:46 -0300848{
849
850/* Temporary hack : use ivtv api until a v4l2 one is available. */
851#define IVTV_IOC_G_CODEC 0xFFEE7703
852#define IVTV_IOC_S_CODEC 0xFFEE7704
853 if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
854 return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
855}
856
857
Adrian Bunk07e337e2006-06-30 11:30:20 -0300858static int pvr2_v4l2_release(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300859{
860 struct pvr2_v4l2_fh *fhp = file->private_data;
861 struct pvr2_v4l2 *vp = fhp->vhead;
862 struct pvr2_context *mp = fhp->vhead->channel.mc_head;
Mike Iselyc74e0062006-12-30 18:31:22 -0300863 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
Mike Iselyd8554972006-06-26 20:58:46 -0300864
865 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
866
867 if (fhp->rhp) {
868 struct pvr2_stream *sp;
Mike Iselyd8554972006-06-26 20:58:46 -0300869 pvr2_hdw_set_streaming(hdw,0);
870 sp = pvr2_ioread_get_stream(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300871 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -0300872 pvr2_ioread_destroy(fhp->rhp);
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300873 fhp->rhp = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300874 }
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300875
Mike Iselyd8554972006-06-26 20:58:46 -0300876 v4l2_prio_close(&vp->prio, &fhp->prio);
877 file->private_data = NULL;
878
879 pvr2_context_enter(mp); do {
Mike Iselyc74e0062006-12-30 18:31:22 -0300880 /* Restore the previous input selection, if it makes sense
881 to do so. */
882 if (fhp->dev_info->v4l_type == VFL_TYPE_RADIO) {
883 struct pvr2_ctrl *cp;
884 int pval;
885 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
886 pvr2_ctrl_get_value(cp,&pval);
887 /* Only restore if we're still selecting the radio */
888 if (pval == PVR2_CVAL_INPUT_RADIO) {
889 pvr2_ctrl_set_value(cp,fhp->prev_input_val);
890 pvr2_hdw_commit_ctl(hdw);
891 }
892 }
893
Mike Iselyd8554972006-06-26 20:58:46 -0300894 if (fhp->vnext) {
895 fhp->vnext->vprev = fhp->vprev;
896 } else {
897 vp->vlast = fhp->vprev;
898 }
899 if (fhp->vprev) {
900 fhp->vprev->vnext = fhp->vnext;
901 } else {
902 vp->vfirst = fhp->vnext;
903 }
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300904 fhp->vnext = NULL;
905 fhp->vprev = NULL;
906 fhp->vhead = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300907 pvr2_channel_done(&fhp->channel);
908 pvr2_trace(PVR2_TRACE_STRUCT,
909 "Destroying pvr_v4l2_fh id=%p",fhp);
910 kfree(fhp);
911 if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
912 pvr2_v4l2_destroy_no_lock(vp);
913 }
914 } while (0); pvr2_context_exit(mp);
915 return 0;
916}
917
918
Adrian Bunk07e337e2006-06-30 11:30:20 -0300919static int pvr2_v4l2_open(struct inode *inode, struct file *file)
Mike Iselyd8554972006-06-26 20:58:46 -0300920{
Mike Isely75910052006-09-23 22:30:50 -0300921 struct pvr2_v4l2_dev *dip; /* Our own context pointer */
Mike Iselyd8554972006-06-26 20:58:46 -0300922 struct pvr2_v4l2_fh *fhp;
923 struct pvr2_v4l2 *vp;
924 struct pvr2_hdw *hdw;
925
Mike Isely75910052006-09-23 22:30:50 -0300926 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
Mike Iselyd8554972006-06-26 20:58:46 -0300927
928 vp = dip->v4lp;
929 hdw = vp->channel.hdw;
930
931 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
932
933 if (!pvr2_hdw_dev_ok(hdw)) {
934 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
935 "pvr2_v4l2_open: hardware not ready");
936 return -EIO;
937 }
938
Mike Isely4b85dee2007-01-20 00:03:32 -0300939 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -0300940 if (!fhp) {
941 return -ENOMEM;
942 }
Mike Iselyd8554972006-06-26 20:58:46 -0300943
944 init_waitqueue_head(&fhp->wait_data);
945 fhp->dev_info = dip;
946
947 pvr2_context_enter(vp->channel.mc_head); do {
948 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
949 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -0300950
Mike Iselya0fd1cb2006-06-30 11:35:28 -0300951 fhp->vnext = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -0300952 fhp->vprev = vp->vlast;
953 if (vp->vlast) {
954 vp->vlast->vnext = fhp;
955 } else {
956 vp->vfirst = fhp;
957 }
958 vp->vlast = fhp;
959 fhp->vhead = vp;
Mike Iselyc74e0062006-12-30 18:31:22 -0300960
961 /* Opening the /dev/radioX device implies a mode switch.
962 So execute that here. Note that you can get the
963 IDENTICAL effect merely by opening the normal video
964 device and setting the input appropriately. */
965 if (dip->v4l_type == VFL_TYPE_RADIO) {
966 struct pvr2_ctrl *cp;
967 cp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
968 pvr2_ctrl_get_value(cp,&fhp->prev_input_val);
969 pvr2_ctrl_set_value(cp,PVR2_CVAL_INPUT_RADIO);
970 pvr2_hdw_commit_ctl(hdw);
971 }
Mike Iselyd8554972006-06-26 20:58:46 -0300972 } while (0); pvr2_context_exit(vp->channel.mc_head);
973
974 fhp->file = file;
975 file->private_data = fhp;
976 v4l2_prio_open(&vp->prio,&fhp->prio);
977
978 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
979
980 return 0;
981}
982
983
984static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
985{
986 wake_up(&fhp->wait_data);
987}
988
989static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
990{
991 int ret;
992 struct pvr2_stream *sp;
993 struct pvr2_hdw *hdw;
994 if (fh->rhp) return 0;
995
Mike Isely16eb40d2006-12-30 18:27:32 -0300996 if (!fh->dev_info->stream) {
997 /* No stream defined for this node. This means that we're
998 not currently allowed to stream from this node. */
999 return -EPERM;
1000 }
1001
Mike Iselyd8554972006-06-26 20:58:46 -03001002 /* First read() attempt. Try to claim the stream and start
1003 it... */
1004 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1005 fh->dev_info->stream)) != 0) {
1006 /* Someone else must already have it */
1007 return ret;
1008 }
1009
1010 fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1011 if (!fh->rhp) {
Mike Iselya0fd1cb2006-06-30 11:35:28 -03001012 pvr2_channel_claim_stream(&fh->channel,NULL);
Mike Iselyd8554972006-06-26 20:58:46 -03001013 return -ENOMEM;
1014 }
1015
1016 hdw = fh->channel.mc_head->hdw;
1017 sp = fh->dev_info->stream->stream;
1018 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1019 pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
Mike Isely681c7392007-11-26 01:48:52 -03001020 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1021 return pvr2_ioread_set_enabled(fh->rhp,!0);
Mike Iselyd8554972006-06-26 20:58:46 -03001022}
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
Mike Iselyd8554972006-06-26 20:58:46 -03001124static 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),
Mike Iselyd8554972006-06-26 20:58:46 -03001130 .fops = &vdev_fops,
1131};
1132
1133
1134static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1135 struct pvr2_v4l2 *vp,
Mike Isely16eb40d2006-12-30 18:27:32 -03001136 int v4l_type)
Mike Iselyd8554972006-06-26 20:58:46 -03001137{
1138 int mindevnum;
1139 int unit_number;
Al Viro89952d12007-03-14 09:17:59 +00001140 int *nr_ptr = NULL;
Mike Iselyd8554972006-06-26 20:58:46 -03001141 dip->v4lp = vp;
Mike Iselyd8554972006-06-26 20:58:46 -03001142
1143
Mike Isely16eb40d2006-12-30 18:27:32 -03001144 dip->v4l_type = v4l_type;
1145 switch (v4l_type) {
1146 case VFL_TYPE_GRABBER:
Mike Iselyd8554972006-06-26 20:58:46 -03001147 dip->stream = &vp->channel.mc_head->video_stream;
Mike Isely16eb40d2006-12-30 18:27:32 -03001148 dip->config = pvr2_config_mpeg;
1149 dip->minor_type = pvr2_v4l_type_video;
1150 nr_ptr = video_nr;
Mike Iselyc74e0062006-12-30 18:31:22 -03001151 if (!dip->stream) {
1152 err("Failed to set up pvrusb2 v4l video dev"
1153 " due to missing stream instance");
1154 return;
1155 }
Mike Iselyd8554972006-06-26 20:58:46 -03001156 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001157 case VFL_TYPE_VBI:
1158 dip->config = pvr2_config_vbi;
1159 dip->minor_type = pvr2_v4l_type_vbi;
1160 nr_ptr = vbi_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001161 break;
Mike Isely16eb40d2006-12-30 18:27:32 -03001162 case VFL_TYPE_RADIO:
Mike Iselyaf78a482007-01-20 00:04:31 -03001163 dip->stream = &vp->channel.mc_head->video_stream;
1164 dip->config = pvr2_config_mpeg;
Mike Isely16eb40d2006-12-30 18:27:32 -03001165 dip->minor_type = pvr2_v4l_type_radio;
1166 nr_ptr = radio_nr;
Mike Iselyd8554972006-06-26 20:58:46 -03001167 break;
1168 default:
1169 /* Bail out (this should be impossible) */
1170 err("Failed to set up pvrusb2 v4l dev"
1171 " due to unrecognized config");
1172 return;
1173 }
1174
Mike Isely75910052006-09-23 22:30:50 -03001175 memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1176 dip->devbase.release = pvr2_video_device_release;
Mike Iselyd8554972006-06-26 20:58:46 -03001177
1178 mindevnum = -1;
1179 unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
Mike Isely16eb40d2006-12-30 18:27:32 -03001180 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1181 mindevnum = nr_ptr[unit_number];
Mike Iselyd8554972006-06-26 20:58:46 -03001182 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001183 if ((video_register_device(&dip->devbase,
1184 dip->v4l_type, mindevnum) < 0) &&
1185 (video_register_device(&dip->devbase,
1186 dip->v4l_type, -1) < 0)) {
Pantelis Koukousoulasae2b9e22006-12-27 23:09:55 -03001187 err("Failed to register pvrusb2 v4l device");
1188 }
Mike Isely16eb40d2006-12-30 18:27:32 -03001189
1190 printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1191 get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1192 pvr2_config_get_name(dip->config));
Mike Iselyd8554972006-06-26 20:58:46 -03001193
Mike Iselyd8554972006-06-26 20:58:46 -03001194 pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
Mike Isely16eb40d2006-12-30 18:27:32 -03001195 dip->minor_type,dip->devbase.minor);
Mike Iselyd8554972006-06-26 20:58:46 -03001196}
1197
1198
1199struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1200{
1201 struct pvr2_v4l2 *vp;
1202
Mike Isely4b85dee2007-01-20 00:03:32 -03001203 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
Mike Iselyd8554972006-06-26 20:58:46 -03001204 if (!vp) return vp;
Mike Isely4b85dee2007-01-20 00:03:32 -03001205 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1206 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
Mike Isely0f0f2572006-12-27 23:19:42 -03001207 if (!(vp->dev_video && vp->dev_radio)) {
Mike Isely6710fb82007-01-20 00:02:26 -03001208 kfree(vp->dev_video);
1209 kfree(vp->dev_radio);
Mike Isely75910052006-09-23 22:30:50 -03001210 kfree(vp);
Randy Dunlapc2625bf2006-10-29 11:12:27 -03001211 return NULL;
Mike Isely75910052006-09-23 22:30:50 -03001212 }
Mike Iselyd8554972006-06-26 20:58:46 -03001213 pvr2_channel_init(&vp->channel,mnp);
1214 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1215
1216 vp->channel.check_func = pvr2_v4l2_internal_check;
1217
1218 /* register streams */
Mike Isely16eb40d2006-12-30 18:27:32 -03001219 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1220 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
Mike Iselyd8554972006-06-26 20:58:46 -03001221
1222 return vp;
1223}
1224
1225/*
1226 Stuff for Emacs to see, in order to encourage consistent editing style:
1227 *** Local Variables: ***
1228 *** mode: c ***
1229 *** fill-column: 75 ***
1230 *** tab-width: 8 ***
1231 *** c-basic-offset: 8 ***
1232 *** End: ***
1233 */