Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[linux-2.6] / drivers / media / video / pvrusb2 / pvrusb2-v4l2.c
1 /*
2  *
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5  *  Copyright (C) 2004 Aurelien Alleaume <slts@free.fr>
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include <linux/kernel.h>
23 #include <linux/version.h>
24 #include "pvrusb2-context.h"
25 #include "pvrusb2-hdw.h"
26 #include "pvrusb2.h"
27 #include "pvrusb2-debug.h"
28 #include "pvrusb2-v4l2.h"
29 #include "pvrusb2-ioread.h"
30 #include <linux/videodev2.h>
31 #include <media/v4l2-dev.h>
32 #include <media/v4l2-common.h>
33 #include <media/v4l2-ioctl.h>
34
35 struct pvr2_v4l2_dev;
36 struct pvr2_v4l2_fh;
37 struct pvr2_v4l2;
38
39 struct pvr2_v4l2_dev {
40         struct video_device devbase; /* MUST be first! */
41         struct pvr2_v4l2 *v4lp;
42         struct pvr2_context_stream *stream;
43         /* 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 */
47 };
48
49 struct pvr2_v4l2_fh {
50         struct pvr2_channel channel;
51         struct pvr2_v4l2_dev *dev_info;
52         enum v4l2_priority prio;
53         struct pvr2_ioread *rhp;
54         struct file *file;
55         struct pvr2_v4l2 *vhead;
56         struct pvr2_v4l2_fh *vnext;
57         struct pvr2_v4l2_fh *vprev;
58         wait_queue_head_t wait_data;
59         int fw_mode_flag;
60         /* Map contiguous ordinal value to input id */
61         unsigned char *input_map;
62         unsigned int input_cnt;
63 };
64
65 struct pvr2_v4l2 {
66         struct pvr2_channel channel;
67         struct pvr2_v4l2_fh *vfirst;
68         struct pvr2_v4l2_fh *vlast;
69
70         struct v4l2_prio_state prio;
71
72         /* streams - Note that these must be separately, individually,
73          * allocated pointers.  This is because the v4l core is going to
74          * manage their deletion - separately, individually...  */
75         struct pvr2_v4l2_dev *dev_video;
76         struct pvr2_v4l2_dev *dev_radio;
77 };
78
79 static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
80 module_param_array(video_nr, int, NULL, 0444);
81 MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
82 static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
83 module_param_array(radio_nr, int, NULL, 0444);
84 MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
85 static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
86 module_param_array(vbi_nr, int, NULL, 0444);
87 MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
88
89 static struct v4l2_capability pvr_capability ={
90         .driver         = "pvrusb2",
91         .card           = "Hauppauge WinTV pvr-usb2",
92         .bus_info       = "usb",
93         .version        = KERNEL_VERSION(0,8,0),
94         .capabilities   = (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
95                            V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
96                            V4L2_CAP_READWRITE),
97         .reserved       = {0,0,0,0}
98 };
99
100 static struct v4l2_fmtdesc pvr_fmtdesc [] = {
101         {
102                 .index          = 0,
103                 .type           = V4L2_BUF_TYPE_VIDEO_CAPTURE,
104                 .flags          = V4L2_FMT_FLAG_COMPRESSED,
105                 .description    = "MPEG1/2",
106                 // This should really be V4L2_PIX_FMT_MPEG, but xawtv
107                 // breaks when I do that.
108                 .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
109                 .reserved       = { 0, 0, 0, 0 }
110         }
111 };
112
113 #define PVR_FORMAT_PIX  0
114 #define PVR_FORMAT_VBI  1
115
116 static struct v4l2_format pvr_format [] = {
117         [PVR_FORMAT_PIX] = {
118                 .type   = V4L2_BUF_TYPE_VIDEO_CAPTURE,
119                 .fmt    = {
120                         .pix        = {
121                                 .width          = 720,
122                                 .height             = 576,
123                                 // This should really be V4L2_PIX_FMT_MPEG,
124                                 // but xawtv breaks when I do that.
125                                 .pixelformat    = 0, // V4L2_PIX_FMT_MPEG,
126                                 .field          = V4L2_FIELD_INTERLACED,
127                                 .bytesperline   = 0,  // doesn't make sense
128                                                       // here
129                                 //FIXME : Don't know what to put here...
130                                 .sizeimage          = (32*1024),
131                                 .colorspace     = 0, // doesn't make sense here
132                                 .priv           = 0
133                         }
134                 }
135         },
136         [PVR_FORMAT_VBI] = {
137                 .type   = V4L2_BUF_TYPE_VBI_CAPTURE,
138                 .fmt    = {
139                         .vbi        = {
140                                 .sampling_rate = 27000000,
141                                 .offset = 248,
142                                 .samples_per_line = 1443,
143                                 .sample_format = V4L2_PIX_FMT_GREY,
144                                 .start = { 0, 0 },
145                                 .count = { 0, 0 },
146                                 .flags = 0,
147                                 .reserved = { 0, 0 }
148                         }
149                 }
150         }
151 };
152
153
154 static const char *get_v4l_name(int v4l_type)
155 {
156         switch (v4l_type) {
157         case VFL_TYPE_GRABBER: return "video";
158         case VFL_TYPE_RADIO: return "radio";
159         case VFL_TYPE_VBI: return "vbi";
160         default: return "?";
161         }
162 }
163
164
165 /*
166  * pvr_ioctl()
167  *
168  * This is part of Video 4 Linux API. The procedure handles ioctl() calls.
169  *
170  */
171 static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file,
172                               unsigned int cmd, void *arg)
173 {
174         struct pvr2_v4l2_fh *fh = file->private_data;
175         struct pvr2_v4l2 *vp = fh->vhead;
176         struct pvr2_v4l2_dev *dev_info = fh->dev_info;
177         struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
178         int ret = -EINVAL;
179
180         if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
181                 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),cmd);
182         }
183
184         if (!pvr2_hdw_dev_ok(hdw)) {
185                 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
186                            "ioctl failed - bad or no context");
187                 return -EFAULT;
188         }
189
190         /* check priority */
191         switch (cmd) {
192         case VIDIOC_S_CTRL:
193         case VIDIOC_S_STD:
194         case VIDIOC_S_INPUT:
195         case VIDIOC_S_TUNER:
196         case VIDIOC_S_FREQUENCY:
197                 ret = v4l2_prio_check(&vp->prio, &fh->prio);
198                 if (ret)
199                         return ret;
200         }
201
202         switch (cmd) {
203         case VIDIOC_QUERYCAP:
204         {
205                 struct v4l2_capability *cap = arg;
206
207                 memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
208                 strlcpy(cap->bus_info,pvr2_hdw_get_bus_info(hdw),
209                         sizeof(cap->bus_info));
210                 strlcpy(cap->card,pvr2_hdw_get_desc(hdw),sizeof(cap->card));
211
212                 ret = 0;
213                 break;
214         }
215
216         case VIDIOC_G_PRIORITY:
217         {
218                 enum v4l2_priority *p = arg;
219
220                 *p = v4l2_prio_max(&vp->prio);
221                 ret = 0;
222                 break;
223         }
224
225         case VIDIOC_S_PRIORITY:
226         {
227                 enum v4l2_priority *prio = arg;
228
229                 ret = v4l2_prio_change(&vp->prio, &fh->prio, *prio);
230                 break;
231         }
232
233         case VIDIOC_ENUMSTD:
234         {
235                 struct v4l2_standard *vs = (struct v4l2_standard *)arg;
236                 int idx = vs->index;
237                 ret = pvr2_hdw_get_stdenum_value(hdw,vs,idx+1);
238                 break;
239         }
240
241         case VIDIOC_G_STD:
242         {
243                 int val = 0;
244                 ret = pvr2_ctrl_get_value(
245                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),&val);
246                 *(v4l2_std_id *)arg = val;
247                 break;
248         }
249
250         case VIDIOC_S_STD:
251         {
252                 ret = pvr2_ctrl_set_value(
253                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_STDCUR),
254                         *(v4l2_std_id *)arg);
255                 break;
256         }
257
258         case VIDIOC_ENUMINPUT:
259         {
260                 struct pvr2_ctrl *cptr;
261                 struct v4l2_input *vi = (struct v4l2_input *)arg;
262                 struct v4l2_input tmp;
263                 unsigned int cnt;
264                 int val;
265
266                 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
267
268                 memset(&tmp,0,sizeof(tmp));
269                 tmp.index = vi->index;
270                 ret = 0;
271                 if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
272                         ret = -EINVAL;
273                         break;
274                 }
275                 val = fh->input_map[vi->index];
276                 switch (val) {
277                 case PVR2_CVAL_INPUT_TV:
278                 case PVR2_CVAL_INPUT_DTV:
279                 case PVR2_CVAL_INPUT_RADIO:
280                         tmp.type = V4L2_INPUT_TYPE_TUNER;
281                         break;
282                 case PVR2_CVAL_INPUT_SVIDEO:
283                 case PVR2_CVAL_INPUT_COMPOSITE:
284                         tmp.type = V4L2_INPUT_TYPE_CAMERA;
285                         break;
286                 default:
287                         ret = -EINVAL;
288                         break;
289                 }
290                 if (ret < 0) break;
291
292                 cnt = 0;
293                 pvr2_ctrl_get_valname(cptr,val,
294                                       tmp.name,sizeof(tmp.name)-1,&cnt);
295                 tmp.name[cnt] = 0;
296
297                 /* Don't bother with audioset, since this driver currently
298                    always switches the audio whenever the video is
299                    switched. */
300
301                 /* Handling std is a tougher problem.  It doesn't make
302                    sense in cases where a device might be multi-standard.
303                    We could just copy out the current value for the
304                    standard, but it can change over time.  For now just
305                    leave it zero. */
306
307                 memcpy(vi, &tmp, sizeof(tmp));
308
309                 ret = 0;
310                 break;
311         }
312
313         case VIDIOC_G_INPUT:
314         {
315                 unsigned int idx;
316                 struct pvr2_ctrl *cptr;
317                 struct v4l2_input *vi = (struct v4l2_input *)arg;
318                 int val;
319                 cptr = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
320                 val = 0;
321                 ret = pvr2_ctrl_get_value(cptr,&val);
322                 vi->index = 0;
323                 for (idx = 0; idx < fh->input_cnt; idx++) {
324                         if (fh->input_map[idx] == val) {
325                                 vi->index = idx;
326                                 break;
327                         }
328                 }
329                 break;
330         }
331
332         case VIDIOC_S_INPUT:
333         {
334                 struct v4l2_input *vi = (struct v4l2_input *)arg;
335                 if ((vi->index < 0) || (vi->index >= fh->input_cnt)) {
336                         ret = -ERANGE;
337                         break;
338                 }
339                 ret = pvr2_ctrl_set_value(
340                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
341                         fh->input_map[vi->index]);
342                 break;
343         }
344
345         case VIDIOC_ENUMAUDIO:
346         {
347                 /* pkt: FIXME: We are returning one "fake" input here
348                    which could very well be called "whatever_we_like".
349                    This is for apps that want to see an audio input
350                    just to feel comfortable, as well as to test if
351                    it can do stereo or sth. There is actually no guarantee
352                    that the actual audio input cannot change behind the app's
353                    back, but most applications should not mind that either.
354
355                    Hopefully, mplayer people will work with us on this (this
356                    whole mess is to support mplayer pvr://), or Hans will come
357                    up with a more standard way to say "we have inputs but we
358                    don 't want you to change them independent of video" which
359                    will sort this mess.
360                  */
361                 struct v4l2_audio *vin = arg;
362                 ret = -EINVAL;
363                 if (vin->index > 0) break;
364                 strncpy(vin->name, "PVRUSB2 Audio",14);
365                 vin->capability = V4L2_AUDCAP_STEREO;
366                 ret = 0;
367                 break;
368                 break;
369         }
370
371         case VIDIOC_G_AUDIO:
372         {
373                 /* pkt: FIXME: see above comment (VIDIOC_ENUMAUDIO) */
374                 struct v4l2_audio *vin = arg;
375                 memset(vin,0,sizeof(*vin));
376                 vin->index = 0;
377                 strncpy(vin->name, "PVRUSB2 Audio",14);
378                 vin->capability = V4L2_AUDCAP_STEREO;
379                 ret = 0;
380                 break;
381         }
382
383         case VIDIOC_S_AUDIO:
384         {
385                 ret = -EINVAL;
386                 break;
387         }
388         case VIDIOC_G_TUNER:
389         {
390                 struct v4l2_tuner *vt = (struct v4l2_tuner *)arg;
391
392                 if (vt->index != 0) break; /* Only answer for the 1st tuner */
393
394                 pvr2_hdw_execute_tuner_poll(hdw);
395                 ret = pvr2_hdw_get_tuner_status(hdw,vt);
396                 break;
397         }
398
399         case VIDIOC_S_TUNER:
400         {
401                 struct v4l2_tuner *vt=(struct v4l2_tuner *)arg;
402
403                 if (vt->index != 0)
404                         break;
405
406                 ret = pvr2_ctrl_set_value(
407                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_AUDIOMODE),
408                         vt->audmode);
409                 break;
410         }
411
412         case VIDIOC_S_FREQUENCY:
413         {
414                 const struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
415                 unsigned long fv;
416                 struct v4l2_tuner vt;
417                 int cur_input;
418                 struct pvr2_ctrl *ctrlp;
419                 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
420                 if (ret != 0) break;
421                 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT);
422                 ret = pvr2_ctrl_get_value(ctrlp,&cur_input);
423                 if (ret != 0) break;
424                 if (vf->type == V4L2_TUNER_RADIO) {
425                         if (cur_input != PVR2_CVAL_INPUT_RADIO) {
426                                 pvr2_ctrl_set_value(ctrlp,
427                                                     PVR2_CVAL_INPUT_RADIO);
428                         }
429                 } else {
430                         if (cur_input == PVR2_CVAL_INPUT_RADIO) {
431                                 pvr2_ctrl_set_value(ctrlp,
432                                                     PVR2_CVAL_INPUT_TV);
433                         }
434                 }
435                 fv = vf->frequency;
436                 if (vt.capability & V4L2_TUNER_CAP_LOW) {
437                         fv = (fv * 125) / 2;
438                 } else {
439                         fv = fv * 62500;
440                 }
441                 ret = pvr2_ctrl_set_value(
442                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
443                 break;
444         }
445
446         case VIDIOC_G_FREQUENCY:
447         {
448                 struct v4l2_frequency *vf = (struct v4l2_frequency *)arg;
449                 int val = 0;
450                 int cur_input;
451                 struct v4l2_tuner vt;
452                 ret = pvr2_hdw_get_tuner_status(hdw,&vt);
453                 if (ret != 0) break;
454                 ret = pvr2_ctrl_get_value(
455                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),
456                         &val);
457                 if (ret != 0) break;
458                 pvr2_ctrl_get_value(
459                         pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT),
460                         &cur_input);
461                 if (cur_input == PVR2_CVAL_INPUT_RADIO) {
462                         vf->type = V4L2_TUNER_RADIO;
463                 } else {
464                         vf->type = V4L2_TUNER_ANALOG_TV;
465                 }
466                 if (vt.capability & V4L2_TUNER_CAP_LOW) {
467                         val = (val * 2) / 125;
468                 } else {
469                         val /= 62500;
470                 }
471                 vf->frequency = val;
472                 break;
473         }
474
475         case VIDIOC_ENUM_FMT:
476         {
477                 struct v4l2_fmtdesc *fd = (struct v4l2_fmtdesc *)arg;
478
479                 /* Only one format is supported : mpeg.*/
480                 if (fd->index != 0)
481                         break;
482
483                 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
484                 ret = 0;
485                 break;
486         }
487
488         case VIDIOC_G_FMT:
489         {
490                 struct v4l2_format *vf = (struct v4l2_format *)arg;
491                 int val;
492                 switch(vf->type) {
493                 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
494                         memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
495                                sizeof(struct v4l2_format));
496                         val = 0;
497                         pvr2_ctrl_get_value(
498                                 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES),
499                                 &val);
500                         vf->fmt.pix.width = val;
501                         val = 0;
502                         pvr2_ctrl_get_value(
503                                 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES),
504                                 &val);
505                         vf->fmt.pix.height = val;
506                         ret = 0;
507                         break;
508                 case V4L2_BUF_TYPE_VBI_CAPTURE:
509                         // ????? Still need to figure out to do VBI correctly
510                         ret = -EINVAL;
511                         break;
512                 default:
513                         ret = -EINVAL;
514                         break;
515                 }
516                 break;
517         }
518
519         case VIDIOC_TRY_FMT:
520         case VIDIOC_S_FMT:
521         {
522                 struct v4l2_format *vf = (struct v4l2_format *)arg;
523
524                 ret = 0;
525                 switch(vf->type) {
526                 case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
527                         int lmin,lmax,ldef;
528                         struct pvr2_ctrl *hcp,*vcp;
529                         int h = vf->fmt.pix.height;
530                         int w = vf->fmt.pix.width;
531                         hcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_HRES);
532                         vcp = pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_VRES);
533
534                         lmin = pvr2_ctrl_get_min(hcp);
535                         lmax = pvr2_ctrl_get_max(hcp);
536                         ldef = pvr2_ctrl_get_def(hcp);
537                         if (w == -1) {
538                                 w = ldef;
539                         } else if (w < lmin) {
540                                 w = lmin;
541                         } else if (w > lmax) {
542                                 w = lmax;
543                         }
544                         lmin = pvr2_ctrl_get_min(vcp);
545                         lmax = pvr2_ctrl_get_max(vcp);
546                         ldef = pvr2_ctrl_get_def(vcp);
547                         if (h == -1) {
548                                 h = ldef;
549                         } else if (h < lmin) {
550                                 h = lmin;
551                         } else if (h > lmax) {
552                                 h = lmax;
553                         }
554
555                         memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
556                                sizeof(struct v4l2_format));
557                         vf->fmt.pix.width = w;
558                         vf->fmt.pix.height = h;
559
560                         if (cmd == VIDIOC_S_FMT) {
561                                 pvr2_ctrl_set_value(hcp,vf->fmt.pix.width);
562                                 pvr2_ctrl_set_value(vcp,vf->fmt.pix.height);
563                         }
564                 } break;
565                 case V4L2_BUF_TYPE_VBI_CAPTURE:
566                         // ????? Still need to figure out to do VBI correctly
567                         ret = -EINVAL;
568                         break;
569                 default:
570                         ret = -EINVAL;
571                         break;
572                 }
573                 break;
574         }
575
576         case VIDIOC_STREAMON:
577         {
578                 if (!fh->dev_info->stream) {
579                         /* No stream defined for this node.  This means
580                            that we're not currently allowed to stream from
581                            this node. */
582                         ret = -EPERM;
583                         break;
584                 }
585                 ret = pvr2_hdw_set_stream_type(hdw,dev_info->config);
586                 if (ret < 0) return ret;
587                 ret = pvr2_hdw_set_streaming(hdw,!0);
588                 break;
589         }
590
591         case VIDIOC_STREAMOFF:
592         {
593                 if (!fh->dev_info->stream) {
594                         /* No stream defined for this node.  This means
595                            that we're not currently allowed to stream from
596                            this node. */
597                         ret = -EPERM;
598                         break;
599                 }
600                 ret = pvr2_hdw_set_streaming(hdw,0);
601                 break;
602         }
603
604         case VIDIOC_QUERYCTRL:
605         {
606                 struct pvr2_ctrl *cptr;
607                 struct v4l2_queryctrl *vc = (struct v4l2_queryctrl *)arg;
608                 ret = 0;
609                 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
610                         cptr = pvr2_hdw_get_ctrl_nextv4l(
611                                 hdw,(vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
612                         if (cptr) vc->id = pvr2_ctrl_get_v4lid(cptr);
613                 } else {
614                         cptr = pvr2_hdw_get_ctrl_v4l(hdw,vc->id);
615                 }
616                 if (!cptr) {
617                         pvr2_trace(PVR2_TRACE_V4LIOCTL,
618                                    "QUERYCTRL id=0x%x not implemented here",
619                                    vc->id);
620                         ret = -EINVAL;
621                         break;
622                 }
623
624                 pvr2_trace(PVR2_TRACE_V4LIOCTL,
625                            "QUERYCTRL id=0x%x mapping name=%s (%s)",
626                            vc->id,pvr2_ctrl_get_name(cptr),
627                            pvr2_ctrl_get_desc(cptr));
628                 strlcpy(vc->name,pvr2_ctrl_get_desc(cptr),sizeof(vc->name));
629                 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
630                 vc->default_value = pvr2_ctrl_get_def(cptr);
631                 switch (pvr2_ctrl_get_type(cptr)) {
632                 case pvr2_ctl_enum:
633                         vc->type = V4L2_CTRL_TYPE_MENU;
634                         vc->minimum = 0;
635                         vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
636                         vc->step = 1;
637                         break;
638                 case pvr2_ctl_bool:
639                         vc->type = V4L2_CTRL_TYPE_BOOLEAN;
640                         vc->minimum = 0;
641                         vc->maximum = 1;
642                         vc->step = 1;
643                         break;
644                 case pvr2_ctl_int:
645                         vc->type = V4L2_CTRL_TYPE_INTEGER;
646                         vc->minimum = pvr2_ctrl_get_min(cptr);
647                         vc->maximum = pvr2_ctrl_get_max(cptr);
648                         vc->step = 1;
649                         break;
650                 default:
651                         pvr2_trace(PVR2_TRACE_V4LIOCTL,
652                                    "QUERYCTRL id=0x%x name=%s not mappable",
653                                    vc->id,pvr2_ctrl_get_name(cptr));
654                         ret = -EINVAL;
655                         break;
656                 }
657                 break;
658         }
659
660         case VIDIOC_QUERYMENU:
661         {
662                 struct v4l2_querymenu *vm = (struct v4l2_querymenu *)arg;
663                 unsigned int cnt = 0;
664                 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw,vm->id),
665                                             vm->index,
666                                             vm->name,sizeof(vm->name)-1,
667                                             &cnt);
668                 vm->name[cnt] = 0;
669                 break;
670         }
671
672         case VIDIOC_G_CTRL:
673         {
674                 struct v4l2_control *vc = (struct v4l2_control *)arg;
675                 int val = 0;
676                 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
677                                           &val);
678                 vc->value = val;
679                 break;
680         }
681
682         case VIDIOC_S_CTRL:
683         {
684                 struct v4l2_control *vc = (struct v4l2_control *)arg;
685                 ret = pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw,vc->id),
686                                           vc->value);
687                 break;
688         }
689
690         case VIDIOC_G_EXT_CTRLS:
691         {
692                 struct v4l2_ext_controls *ctls =
693                         (struct v4l2_ext_controls *)arg;
694                 struct v4l2_ext_control *ctrl;
695                 unsigned int idx;
696                 int val;
697                 ret = 0;
698                 for (idx = 0; idx < ctls->count; idx++) {
699                         ctrl = ctls->controls + idx;
700                         ret = pvr2_ctrl_get_value(
701                                 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),&val);
702                         if (ret) {
703                                 ctls->error_idx = idx;
704                                 break;
705                         }
706                         /* Ensure that if read as a 64 bit value, the user
707                            will still get a hopefully sane value */
708                         ctrl->value64 = 0;
709                         ctrl->value = val;
710                 }
711                 break;
712         }
713
714         case VIDIOC_S_EXT_CTRLS:
715         {
716                 struct v4l2_ext_controls *ctls =
717                         (struct v4l2_ext_controls *)arg;
718                 struct v4l2_ext_control *ctrl;
719                 unsigned int idx;
720                 ret = 0;
721                 for (idx = 0; idx < ctls->count; idx++) {
722                         ctrl = ctls->controls + idx;
723                         ret = pvr2_ctrl_set_value(
724                                 pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id),
725                                 ctrl->value);
726                         if (ret) {
727                                 ctls->error_idx = idx;
728                                 break;
729                         }
730                 }
731                 break;
732         }
733
734         case VIDIOC_TRY_EXT_CTRLS:
735         {
736                 struct v4l2_ext_controls *ctls =
737                         (struct v4l2_ext_controls *)arg;
738                 struct v4l2_ext_control *ctrl;
739                 struct pvr2_ctrl *pctl;
740                 unsigned int idx;
741                 /* For the moment just validate that the requested control
742                    actually exists. */
743                 ret = 0;
744                 for (idx = 0; idx < ctls->count; idx++) {
745                         ctrl = ctls->controls + idx;
746                         pctl = pvr2_hdw_get_ctrl_v4l(hdw,ctrl->id);
747                         if (!pctl) {
748                                 ret = -EINVAL;
749                                 ctls->error_idx = idx;
750                                 break;
751                         }
752                 }
753                 break;
754         }
755
756         case VIDIOC_LOG_STATUS:
757         {
758                 pvr2_hdw_trigger_module_log(hdw);
759                 ret = 0;
760                 break;
761         }
762 #ifdef CONFIG_VIDEO_ADV_DEBUG
763         case VIDIOC_DBG_S_REGISTER:
764         case VIDIOC_DBG_G_REGISTER:
765         {
766                 u64 val;
767                 struct v4l2_register *req = (struct v4l2_register *)arg;
768                 if (cmd == VIDIOC_DBG_S_REGISTER) val = req->val;
769                 ret = pvr2_hdw_register_access(
770                         hdw,req->match_type,req->match_chip,req->reg,
771                         cmd == VIDIOC_DBG_S_REGISTER,&val);
772                 if (cmd == VIDIOC_DBG_G_REGISTER) req->val = val;
773                 break;
774         }
775 #endif
776
777         default :
778                 ret = v4l_compat_translate_ioctl(inode,file,cmd,
779                                                  arg,pvr2_v4l2_do_ioctl);
780         }
781
782         pvr2_hdw_commit_ctl(hdw);
783
784         if (ret < 0) {
785                 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
786                         pvr2_trace(PVR2_TRACE_V4LIOCTL,
787                                    "pvr2_v4l2_do_ioctl failure, ret=%d",ret);
788                 } else {
789                         if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
790                                 pvr2_trace(PVR2_TRACE_V4LIOCTL,
791                                            "pvr2_v4l2_do_ioctl failure, ret=%d"
792                                            " command was:",ret);
793                                 v4l_print_ioctl(pvr2_hdw_get_driver_name(hdw),
794                                                 cmd);
795                         }
796                 }
797         } else {
798                 pvr2_trace(PVR2_TRACE_V4LIOCTL,
799                            "pvr2_v4l2_do_ioctl complete, ret=%d (0x%x)",
800                            ret,ret);
801         }
802         return ret;
803 }
804
805
806 static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
807 {
808         int minor_id = dip->devbase.minor;
809         struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
810         enum pvr2_config cfg = dip->config;
811         int v4l_type = dip->v4l_type;
812
813         pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
814
815         /* Paranoia */
816         dip->v4lp = NULL;
817         dip->stream = NULL;
818
819         /* Actual deallocation happens later when all internal references
820            are gone. */
821         video_unregister_device(&dip->devbase);
822
823         printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n",
824                get_v4l_name(v4l_type),minor_id & 0x1f,
825                pvr2_config_get_name(cfg));
826
827 }
828
829
830 static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
831 {
832         if (vp->dev_video) {
833                 pvr2_v4l2_dev_destroy(vp->dev_video);
834                 vp->dev_video = NULL;
835         }
836         if (vp->dev_radio) {
837                 pvr2_v4l2_dev_destroy(vp->dev_radio);
838                 vp->dev_radio = NULL;
839         }
840
841         pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
842         pvr2_channel_done(&vp->channel);
843         kfree(vp);
844 }
845
846
847 static void pvr2_video_device_release(struct video_device *vdev)
848 {
849         struct pvr2_v4l2_dev *dev;
850         dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
851         kfree(dev);
852 }
853
854
855 static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
856 {
857         struct pvr2_v4l2 *vp;
858         vp = container_of(chp,struct pvr2_v4l2,channel);
859         if (!vp->channel.mc_head->disconnect_flag) return;
860         if (vp->vfirst) return;
861         pvr2_v4l2_destroy_no_lock(vp);
862 }
863
864
865 static int pvr2_v4l2_ioctl(struct inode *inode, struct file *file,
866                            unsigned int cmd, unsigned long arg)
867 {
868
869 /* Temporary hack : use ivtv api until a v4l2 one is available. */
870 #define IVTV_IOC_G_CODEC        0xFFEE7703
871 #define IVTV_IOC_S_CODEC        0xFFEE7704
872         if (cmd == IVTV_IOC_G_CODEC || cmd == IVTV_IOC_S_CODEC) return 0;
873         return video_usercopy(inode, file, cmd, arg, pvr2_v4l2_do_ioctl);
874 }
875
876
877 static int pvr2_v4l2_release(struct inode *inode, struct file *file)
878 {
879         struct pvr2_v4l2_fh *fhp = file->private_data;
880         struct pvr2_v4l2 *vp = fhp->vhead;
881         struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
882
883         pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
884
885         if (fhp->rhp) {
886                 struct pvr2_stream *sp;
887                 pvr2_hdw_set_streaming(hdw,0);
888                 sp = pvr2_ioread_get_stream(fhp->rhp);
889                 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
890                 pvr2_ioread_destroy(fhp->rhp);
891                 fhp->rhp = NULL;
892         }
893
894         v4l2_prio_close(&vp->prio, &fhp->prio);
895         file->private_data = NULL;
896
897         if (fhp->vnext) {
898                 fhp->vnext->vprev = fhp->vprev;
899         } else {
900                 vp->vlast = fhp->vprev;
901         }
902         if (fhp->vprev) {
903                 fhp->vprev->vnext = fhp->vnext;
904         } else {
905                 vp->vfirst = fhp->vnext;
906         }
907         fhp->vnext = NULL;
908         fhp->vprev = NULL;
909         fhp->vhead = NULL;
910         pvr2_channel_done(&fhp->channel);
911         pvr2_trace(PVR2_TRACE_STRUCT,
912                    "Destroying pvr_v4l2_fh id=%p",fhp);
913         if (fhp->input_map) {
914                 kfree(fhp->input_map);
915                 fhp->input_map = NULL;
916         }
917         kfree(fhp);
918         if (vp->channel.mc_head->disconnect_flag && !vp->vfirst) {
919                 pvr2_v4l2_destroy_no_lock(vp);
920         }
921         return 0;
922 }
923
924
925 static int pvr2_v4l2_open(struct inode *inode, struct file *file)
926 {
927         struct pvr2_v4l2_dev *dip; /* Our own context pointer */
928         struct pvr2_v4l2_fh *fhp;
929         struct pvr2_v4l2 *vp;
930         struct pvr2_hdw *hdw;
931         unsigned int input_mask = 0;
932         unsigned int input_cnt,idx;
933         int ret = 0;
934
935         dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
936
937         vp = dip->v4lp;
938         hdw = vp->channel.hdw;
939
940         pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
941
942         if (!pvr2_hdw_dev_ok(hdw)) {
943                 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
944                            "pvr2_v4l2_open: hardware not ready");
945                 return -EIO;
946         }
947
948         fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
949         if (!fhp) {
950                 return -ENOMEM;
951         }
952
953         init_waitqueue_head(&fhp->wait_data);
954         fhp->dev_info = dip;
955
956         pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
957         pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
958
959         if (dip->v4l_type == VFL_TYPE_RADIO) {
960                 /* Opening device as a radio, legal input selection subset
961                    is just the radio. */
962                 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
963         } else {
964                 /* Opening the main V4L device, legal input selection
965                    subset includes all analog inputs. */
966                 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
967                               (1 << PVR2_CVAL_INPUT_TV) |
968                               (1 << PVR2_CVAL_INPUT_COMPOSITE) |
969                               (1 << PVR2_CVAL_INPUT_SVIDEO));
970         }
971         ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
972         if (ret) {
973                 pvr2_channel_done(&fhp->channel);
974                 pvr2_trace(PVR2_TRACE_STRUCT,
975                            "Destroying pvr_v4l2_fh id=%p (input mask error)",
976                            fhp);
977
978                 kfree(fhp);
979                 return ret;
980         }
981
982         input_mask &= pvr2_hdw_get_input_available(hdw);
983         input_cnt = 0;
984         for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
985                 if (input_mask & (1 << idx)) input_cnt++;
986         }
987         fhp->input_cnt = input_cnt;
988         fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
989         if (!fhp->input_map) {
990                 pvr2_channel_done(&fhp->channel);
991                 pvr2_trace(PVR2_TRACE_STRUCT,
992                            "Destroying pvr_v4l2_fh id=%p (input map failure)",
993                            fhp);
994                 kfree(fhp);
995                 return -ENOMEM;
996         }
997         input_cnt = 0;
998         for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
999                 if (!(input_mask & (1 << idx))) continue;
1000                 fhp->input_map[input_cnt++] = idx;
1001         }
1002
1003         fhp->vnext = NULL;
1004         fhp->vprev = vp->vlast;
1005         if (vp->vlast) {
1006                 vp->vlast->vnext = fhp;
1007         } else {
1008                 vp->vfirst = fhp;
1009         }
1010         vp->vlast = fhp;
1011         fhp->vhead = vp;
1012
1013         fhp->file = file;
1014         file->private_data = fhp;
1015         v4l2_prio_open(&vp->prio,&fhp->prio);
1016
1017         fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1018
1019         return 0;
1020 }
1021
1022
1023 static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1024 {
1025         wake_up(&fhp->wait_data);
1026 }
1027
1028 static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1029 {
1030         int ret;
1031         struct pvr2_stream *sp;
1032         struct pvr2_hdw *hdw;
1033         if (fh->rhp) return 0;
1034
1035         if (!fh->dev_info->stream) {
1036                 /* No stream defined for this node.  This means that we're
1037                    not currently allowed to stream from this node. */
1038                 return -EPERM;
1039         }
1040
1041         /* First read() attempt.  Try to claim the stream and start
1042            it... */
1043         if ((ret = pvr2_channel_claim_stream(&fh->channel,
1044                                              fh->dev_info->stream)) != 0) {
1045                 /* Someone else must already have it */
1046                 return ret;
1047         }
1048
1049         fh->rhp = pvr2_channel_create_mpeg_stream(fh->dev_info->stream);
1050         if (!fh->rhp) {
1051                 pvr2_channel_claim_stream(&fh->channel,NULL);
1052                 return -ENOMEM;
1053         }
1054
1055         hdw = fh->channel.mc_head->hdw;
1056         sp = fh->dev_info->stream->stream;
1057         pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1058         pvr2_hdw_set_stream_type(hdw,fh->dev_info->config);
1059         if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1060         return pvr2_ioread_set_enabled(fh->rhp,!0);
1061 }
1062
1063
1064 static ssize_t pvr2_v4l2_read(struct file *file,
1065                               char __user *buff, size_t count, loff_t *ppos)
1066 {
1067         struct pvr2_v4l2_fh *fh = file->private_data;
1068         int ret;
1069
1070         if (fh->fw_mode_flag) {
1071                 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1072                 char *tbuf;
1073                 int c1,c2;
1074                 int tcnt = 0;
1075                 unsigned int offs = *ppos;
1076
1077                 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1078                 if (!tbuf) return -ENOMEM;
1079
1080                 while (count) {
1081                         c1 = count;
1082                         if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1083                         c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1084                         if (c2 < 0) {
1085                                 tcnt = c2;
1086                                 break;
1087                         }
1088                         if (!c2) break;
1089                         if (copy_to_user(buff,tbuf,c2)) {
1090                                 tcnt = -EFAULT;
1091                                 break;
1092                         }
1093                         offs += c2;
1094                         tcnt += c2;
1095                         buff += c2;
1096                         count -= c2;
1097                         *ppos += c2;
1098                 }
1099                 kfree(tbuf);
1100                 return tcnt;
1101         }
1102
1103         if (!fh->rhp) {
1104                 ret = pvr2_v4l2_iosetup(fh);
1105                 if (ret) {
1106                         return ret;
1107                 }
1108         }
1109
1110         for (;;) {
1111                 ret = pvr2_ioread_read(fh->rhp,buff,count);
1112                 if (ret >= 0) break;
1113                 if (ret != -EAGAIN) break;
1114                 if (file->f_flags & O_NONBLOCK) break;
1115                 /* Doing blocking I/O.  Wait here. */
1116                 ret = wait_event_interruptible(
1117                         fh->wait_data,
1118                         pvr2_ioread_avail(fh->rhp) >= 0);
1119                 if (ret < 0) break;
1120         }
1121
1122         return ret;
1123 }
1124
1125
1126 static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1127 {
1128         unsigned int mask = 0;
1129         struct pvr2_v4l2_fh *fh = file->private_data;
1130         int ret;
1131
1132         if (fh->fw_mode_flag) {
1133                 mask |= POLLIN | POLLRDNORM;
1134                 return mask;
1135         }
1136
1137         if (!fh->rhp) {
1138                 ret = pvr2_v4l2_iosetup(fh);
1139                 if (ret) return POLLERR;
1140         }
1141
1142         poll_wait(file,&fh->wait_data,wait);
1143
1144         if (pvr2_ioread_avail(fh->rhp) >= 0) {
1145                 mask |= POLLIN | POLLRDNORM;
1146         }
1147
1148         return mask;
1149 }
1150
1151
1152 static const struct file_operations vdev_fops = {
1153         .owner      = THIS_MODULE,
1154         .open       = pvr2_v4l2_open,
1155         .release    = pvr2_v4l2_release,
1156         .read       = pvr2_v4l2_read,
1157         .ioctl      = pvr2_v4l2_ioctl,
1158         .llseek     = no_llseek,
1159         .poll       = pvr2_v4l2_poll,
1160 };
1161
1162
1163 static struct video_device vdev_template = {
1164         .fops       = &vdev_fops,
1165 };
1166
1167
1168 static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1169                                struct pvr2_v4l2 *vp,
1170                                int v4l_type)
1171 {
1172         int mindevnum;
1173         int unit_number;
1174         int *nr_ptr = NULL;
1175         dip->v4lp = vp;
1176
1177
1178         dip->v4l_type = v4l_type;
1179         switch (v4l_type) {
1180         case VFL_TYPE_GRABBER:
1181                 dip->stream = &vp->channel.mc_head->video_stream;
1182                 dip->config = pvr2_config_mpeg;
1183                 dip->minor_type = pvr2_v4l_type_video;
1184                 nr_ptr = video_nr;
1185                 if (!dip->stream) {
1186                         err("Failed to set up pvrusb2 v4l video dev"
1187                             " due to missing stream instance");
1188                         return;
1189                 }
1190                 break;
1191         case VFL_TYPE_VBI:
1192                 dip->config = pvr2_config_vbi;
1193                 dip->minor_type = pvr2_v4l_type_vbi;
1194                 nr_ptr = vbi_nr;
1195                 break;
1196         case VFL_TYPE_RADIO:
1197                 dip->stream = &vp->channel.mc_head->video_stream;
1198                 dip->config = pvr2_config_mpeg;
1199                 dip->minor_type = pvr2_v4l_type_radio;
1200                 nr_ptr = radio_nr;
1201                 break;
1202         default:
1203                 /* Bail out (this should be impossible) */
1204                 err("Failed to set up pvrusb2 v4l dev"
1205                     " due to unrecognized config");
1206                 return;
1207         }
1208
1209         memcpy(&dip->devbase,&vdev_template,sizeof(vdev_template));
1210         dip->devbase.release = pvr2_video_device_release;
1211
1212         mindevnum = -1;
1213         unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw);
1214         if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1215                 mindevnum = nr_ptr[unit_number];
1216         }
1217         if ((video_register_device(&dip->devbase,
1218                                    dip->v4l_type, mindevnum) < 0) &&
1219             (video_register_device(&dip->devbase,
1220                                    dip->v4l_type, -1) < 0)) {
1221                 err("Failed to register pvrusb2 v4l device");
1222         }
1223
1224         printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n",
1225                get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f,
1226                pvr2_config_get_name(dip->config));
1227
1228         pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw,
1229                                         dip->minor_type,dip->devbase.minor);
1230 }
1231
1232
1233 struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1234 {
1235         struct pvr2_v4l2 *vp;
1236
1237         vp = kzalloc(sizeof(*vp),GFP_KERNEL);
1238         if (!vp) return vp;
1239         pvr2_channel_init(&vp->channel,mnp);
1240         pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1241
1242         vp->channel.check_func = pvr2_v4l2_internal_check;
1243
1244         /* register streams */
1245         vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1246         if (!vp->dev_video) goto fail;
1247         pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1248         if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1249             (1 << PVR2_CVAL_INPUT_RADIO)) {
1250                 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1251                 if (!vp->dev_radio) goto fail;
1252                 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1253         }
1254
1255         return vp;
1256  fail:
1257         pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1258         pvr2_v4l2_destroy_no_lock(vp);
1259         return NULL;
1260 }
1261
1262 /*
1263   Stuff for Emacs to see, in order to encourage consistent editing style:
1264   *** Local Variables: ***
1265   *** mode: c ***
1266   *** fill-column: 75 ***
1267   *** tab-width: 8 ***
1268   *** c-basic-offset: 8 ***
1269   *** End: ***
1270   */