static inline int radio_function(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct radio_device *card=dev->priv; switch(cmd) { case VIDIOC_QUERYCAP: { struct v4l2_capability *v = arg; memset(v,0,sizeof(*v)); strlcpy(v->driver, "radio-maxiradio", sizeof (v->driver)); strlcpy(v->card, "Maxi Radio FM2000 radio", sizeof (v->card)); sprintf(v->bus_info,"ISA"); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER; return 0; } case VIDIOC_G_TUNER: { struct v4l2_tuner *v = arg; if (v->index > 0) return -EINVAL; memset(v,0,sizeof(*v)); strcpy(v->name, "FM"); v->type = V4L2_TUNER_RADIO; v->rangelow=FREQ_LO; v->rangehigh=FREQ_HI; v->rxsubchans =V4L2_TUNER_SUB_MONO|V4L2_TUNER_SUB_STEREO; v->capability=V4L2_TUNER_CAP_LOW; if(get_stereo(card->io)) v->audmode = V4L2_TUNER_MODE_STEREO; else v->audmode = V4L2_TUNER_MODE_MONO; v->signal=0xffff*get_tune(card->io); return 0; } case VIDIOC_S_TUNER: { struct v4l2_tuner *v = arg; if (v->index > 0) return -EINVAL; return 0; } case VIDIOC_S_FREQUENCY: { struct v4l2_frequency *f = arg; if (f->frequency < FREQ_LO || f->frequency > FREQ_HI) return -EINVAL; card->freq = f->frequency; set_freq(card->io, FREQ2BITS(card->freq)); msleep(125); return 0; } case VIDIOC_G_FREQUENCY: { struct v4l2_frequency *f = arg; f->type = V4L2_TUNER_RADIO; f->frequency = card->freq; return 0; } case VIDIOC_QUERYCTRL: { struct v4l2_queryctrl *qc = arg; int i; for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) { if (qc->id && qc->id == radio_qctrl[i].id) { memcpy(qc, &(radio_qctrl[i]), sizeof(*qc)); return (0); } } return -EINVAL; } case VIDIOC_G_CTRL: { struct v4l2_control *ctrl= arg; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value=card->muted; return (0); } return -EINVAL; } case VIDIOC_S_CTRL: { struct v4l2_control *ctrl= arg; switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: card->muted = ctrl->value; if(card->muted) turn_power(card->io, 0); else set_freq(card->io, FREQ2BITS(card->freq)); return 0; } return -EINVAL; } default: return v4l_compat_translate_ioctl(inode,file,cmd,arg, radio_function); } }
static inline int radio_function(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct video_device *dev = video_devdata(file); struct radio_device *card=dev->priv; switch(cmd) { case VIDIOCGCAP: { struct video_capability *v = arg; memset(v,0,sizeof(*v)); strcpy(v->name, "Maxi Radio FM2000 radio"); v->type=VID_TYPE_TUNER; v->channels=v->audios=1; return 0; } case VIDIOCGTUNER: { struct video_tuner *v = arg; if(v->tuner) return -EINVAL; card->stereo = 0xffff * get_stereo(card->io); card->tuned = 0xffff * get_tune(card->io); v->flags = VIDEO_TUNER_LOW | card->stereo; v->signal = card->tuned; strcpy(v->name, "FM"); v->rangelow = FREQ_LO; v->rangehigh = FREQ_HI; v->mode = VIDEO_MODE_AUTO; return 0; } case VIDIOCSTUNER: { struct video_tuner *v = arg; if(v->tuner!=0) return -EINVAL; return 0; } case VIDIOCGFREQ: { unsigned long *freq = arg; *freq = card->freq; return 0; } case VIDIOCSFREQ: { unsigned long *freq = arg; if (*freq < FREQ_LO || *freq > FREQ_HI) return -EINVAL; card->freq = *freq; set_freq(card->io, FREQ2BITS(card->freq)); msleep(125); return 0; } case VIDIOCGAUDIO: { struct video_audio *v = arg; memset(v,0,sizeof(*v)); strcpy(v->name, "Radio"); v->flags=VIDEO_AUDIO_MUTABLE | card->muted; v->mode=VIDEO_SOUND_STEREO; return 0; } case VIDIOCSAUDIO: { struct video_audio *v = arg; if(v->audio) return -EINVAL; card->muted = v->flags & VIDEO_AUDIO_MUTE; if(card->muted) turn_power(card->io, 0); else set_freq(card->io, FREQ2BITS(card->freq)); return 0; } case VIDIOCGUNIT: { struct video_unit *v = arg; v->video=VIDEO_NO_UNIT; v->vbi=VIDEO_NO_UNIT; v->radio=dev->minor; v->audio=0; v->teletext=VIDEO_NO_UNIT; return 0; } default: return -ENOIOCTLCMD; } }