diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-v4l2.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 186 |
1 files changed, 73 insertions, 113 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index cc3260f37e84..7a8b34dbc363 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c | |||
@@ -40,7 +40,10 @@ struct pvr2_v4l2_dev { | |||
40 | struct video_device devbase; /* MUST be first! */ | 40 | struct video_device devbase; /* MUST be first! */ |
41 | struct pvr2_v4l2 *v4lp; | 41 | struct pvr2_v4l2 *v4lp; |
42 | struct pvr2_context_stream *stream; | 42 | struct pvr2_context_stream *stream; |
43 | enum pvr2_config config; | 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 */ | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | struct pvr2_v4l2_fh { | 49 | struct pvr2_v4l2_fh { |
@@ -163,6 +166,18 @@ static struct v4l2_format pvr_format [] = { | |||
163 | } | 166 | } |
164 | }; | 167 | }; |
165 | 168 | ||
169 | |||
170 | static const char *get_v4l_name(int v4l_type) | ||
171 | { | ||
172 | switch (v4l_type) { | ||
173 | case VFL_TYPE_GRABBER: return "video"; | ||
174 | case VFL_TYPE_RADIO: return "radio"; | ||
175 | case VFL_TYPE_VBI: return "vbi"; | ||
176 | default: return "?"; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | |||
166 | /* | 181 | /* |
167 | * pvr_ioctl() | 182 | * pvr_ioctl() |
168 | * | 183 | * |
@@ -521,6 +536,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
521 | 536 | ||
522 | case VIDIOC_STREAMON: | 537 | case VIDIOC_STREAMON: |
523 | { | 538 | { |
539 | if (!fh->dev_info->stream) { | ||
540 | /* No stream defined for this node. This means | ||
541 | that we're not currently allowed to stream from | ||
542 | this node. */ | ||
543 | ret = -EPERM; | ||
544 | break; | ||
545 | } | ||
524 | ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); | 546 | ret = pvr2_hdw_set_stream_type(hdw,dev_info->config); |
525 | if (ret < 0) return ret; | 547 | if (ret < 0) return ret; |
526 | ret = pvr2_hdw_set_streaming(hdw,!0); | 548 | ret = pvr2_hdw_set_streaming(hdw,!0); |
@@ -529,6 +551,13 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
529 | 551 | ||
530 | case VIDIOC_STREAMOFF: | 552 | case VIDIOC_STREAMOFF: |
531 | { | 553 | { |
554 | if (!fh->dev_info->stream) { | ||
555 | /* No stream defined for this node. This means | ||
556 | that we're not currently allowed to stream from | ||
557 | this node. */ | ||
558 | ret = -EPERM; | ||
559 | break; | ||
560 | } | ||
532 | ret = pvr2_hdw_set_streaming(hdw,0); | 561 | ret = pvr2_hdw_set_streaming(hdw,0); |
533 | break; | 562 | break; |
534 | } | 563 | } |
@@ -734,26 +763,12 @@ static int pvr2_v4l2_do_ioctl(struct inode *inode, struct file *file, | |||
734 | 763 | ||
735 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | 764 | static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) |
736 | { | 765 | { |
737 | enum pvr2_config cfg = dip->config; | ||
738 | int minor_id = dip->devbase.minor; | 766 | int minor_id = dip->devbase.minor; |
739 | enum pvr2_v4l_type pvt; | ||
740 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; | 767 | struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw; |
768 | enum pvr2_config cfg = dip->config; | ||
769 | int v4l_type = dip->v4l_type; | ||
741 | 770 | ||
742 | switch (cfg) { | 771 | pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1); |
743 | case pvr2_config_mpeg: | ||
744 | pvt = pvr2_v4l_type_video; | ||
745 | break; | ||
746 | case pvr2_config_vbi: | ||
747 | pvt = pvr2_v4l_type_vbi; | ||
748 | break; | ||
749 | case pvr2_config_radio: | ||
750 | pvt = pvr2_v4l_type_radio; | ||
751 | break; | ||
752 | default: /* paranoia */ | ||
753 | pvt = pvr2_v4l_type_video; | ||
754 | break; | ||
755 | } | ||
756 | pvr2_hdw_v4l_store_minor_number(hdw,pvt,-1); | ||
757 | 772 | ||
758 | /* Paranoia */ | 773 | /* Paranoia */ |
759 | dip->v4lp = NULL; | 774 | dip->v4lp = NULL; |
@@ -763,25 +778,9 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) | |||
763 | are gone. */ | 778 | are gone. */ |
764 | video_unregister_device(&dip->devbase); | 779 | video_unregister_device(&dip->devbase); |
765 | 780 | ||
766 | switch (cfg) { | 781 | printk(KERN_INFO "pvrusb2: unregistered device %s%u [%s]\n", |
767 | case pvr2_config_mpeg: | 782 | get_v4l_name(v4l_type),minor_id & 0x1f, |
768 | printk(KERN_INFO "pvrusb2: unregistered device video%d [%s]\n", | 783 | pvr2_config_get_name(cfg)); |
769 | minor_id & 0x1f, | ||
770 | pvr2_config_get_name(cfg)); | ||
771 | break; | ||
772 | case pvr2_config_radio: | ||
773 | printk(KERN_INFO "pvrusb2: unregistered device radio%d [%s]\n", | ||
774 | minor_id & 0x1f, | ||
775 | pvr2_config_get_name(cfg)); | ||
776 | break; | ||
777 | case pvr2_config_vbi: | ||
778 | printk(KERN_INFO "pvrusb2: unregistered device vbi%d [%s]\n", | ||
779 | minor_id & 0x1f, | ||
780 | pvr2_config_get_name(cfg)); | ||
781 | break; | ||
782 | default: | ||
783 | break; | ||
784 | } | ||
785 | 784 | ||
786 | } | 785 | } |
787 | 786 | ||
@@ -852,17 +851,6 @@ static int pvr2_v4l2_release(struct inode *inode, struct file *file) | |||
852 | fhp->rhp = NULL; | 851 | fhp->rhp = NULL; |
853 | } | 852 | } |
854 | 853 | ||
855 | if (fhp->dev_info->config == pvr2_config_radio) { | ||
856 | int ret; | ||
857 | struct pvr2_hdw *hdw; | ||
858 | hdw = fhp->channel.mc_head->hdw; | ||
859 | if ((ret = pvr2_ctrl_set_value( | ||
860 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | ||
861 | PVR2_CVAL_INPUT_TV))) { | ||
862 | return ret; | ||
863 | } | ||
864 | } | ||
865 | |||
866 | v4l2_prio_close(&vp->prio, &fhp->prio); | 854 | v4l2_prio_close(&vp->prio, &fhp->prio); |
867 | file->private_data = NULL; | 855 | file->private_data = NULL; |
868 | 856 | ||
@@ -929,7 +917,7 @@ static int pvr2_v4l2_open(struct inode *inode, struct file *file) | |||
929 | So execute that here. Note that you can get the | 917 | So execute that here. Note that you can get the |
930 | IDENTICAL effect merely by opening the normal video | 918 | IDENTICAL effect merely by opening the normal video |
931 | device and setting the input appropriately. */ | 919 | device and setting the input appropriately. */ |
932 | if (dip->config == pvr2_config_radio) { | 920 | if (dip->v4l_type == VFL_TYPE_RADIO) { |
933 | pvr2_ctrl_set_value( | 921 | pvr2_ctrl_set_value( |
934 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), | 922 | pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_INPUT), |
935 | PVR2_CVAL_INPUT_RADIO); | 923 | PVR2_CVAL_INPUT_RADIO); |
@@ -968,6 +956,12 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh) | |||
968 | struct pvr2_hdw *hdw; | 956 | struct pvr2_hdw *hdw; |
969 | if (fh->rhp) return 0; | 957 | if (fh->rhp) return 0; |
970 | 958 | ||
959 | if (!fh->dev_info->stream) { | ||
960 | /* No stream defined for this node. This means that we're | ||
961 | not currently allowed to stream from this node. */ | ||
962 | return -EPERM; | ||
963 | } | ||
964 | |||
971 | /* First read() attempt. Try to claim the stream and start | 965 | /* First read() attempt. Try to claim the stream and start |
972 | it... */ | 966 | it... */ |
973 | if ((ret = pvr2_channel_claim_stream(&fh->channel, | 967 | if ((ret = pvr2_channel_claim_stream(&fh->channel, |
@@ -1032,12 +1026,6 @@ static ssize_t pvr2_v4l2_read(struct file *file, | |||
1032 | return tcnt; | 1026 | return tcnt; |
1033 | } | 1027 | } |
1034 | 1028 | ||
1035 | if (fh->dev_info->config == pvr2_config_radio) { | ||
1036 | /* Radio device nodes on this device | ||
1037 | cannot be read or written. */ | ||
1038 | return -EPERM; | ||
1039 | } | ||
1040 | |||
1041 | if (!fh->rhp) { | 1029 | if (!fh->rhp) { |
1042 | ret = pvr2_v4l2_iosetup(fh); | 1030 | ret = pvr2_v4l2_iosetup(fh); |
1043 | if (ret) { | 1031 | if (ret) { |
@@ -1072,12 +1060,6 @@ static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait) | |||
1072 | return mask; | 1060 | return mask; |
1073 | } | 1061 | } |
1074 | 1062 | ||
1075 | if (fh->dev_info->config == pvr2_config_radio) { | ||
1076 | /* Radio device nodes on this device | ||
1077 | cannot be read or written. */ | ||
1078 | return -EPERM; | ||
1079 | } | ||
1080 | |||
1081 | if (!fh->rhp) { | 1063 | if (!fh->rhp) { |
1082 | ret = pvr2_v4l2_iosetup(fh); | 1064 | ret = pvr2_v4l2_iosetup(fh); |
1083 | if (ret) return POLLERR; | 1065 | if (ret) return POLLERR; |
@@ -1119,29 +1101,31 @@ static struct video_device vdev_template = { | |||
1119 | 1101 | ||
1120 | static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | 1102 | static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, |
1121 | struct pvr2_v4l2 *vp, | 1103 | struct pvr2_v4l2 *vp, |
1122 | enum pvr2_config cfg) | 1104 | int v4l_type) |
1123 | { | 1105 | { |
1124 | int mindevnum; | 1106 | int mindevnum; |
1125 | int unit_number; | 1107 | int unit_number; |
1126 | int v4l_type; | 1108 | int *nr_ptr = 0; |
1127 | enum pvr2_v4l_type pvt; | ||
1128 | dip->v4lp = vp; | 1109 | dip->v4lp = vp; |
1129 | dip->config = cfg; | ||
1130 | 1110 | ||
1131 | 1111 | ||
1132 | switch (dip->config) { | 1112 | dip->v4l_type = v4l_type; |
1133 | case pvr2_config_mpeg: | 1113 | switch (v4l_type) { |
1134 | v4l_type = VFL_TYPE_GRABBER; | 1114 | case VFL_TYPE_GRABBER: |
1135 | pvt = pvr2_v4l_type_video; | ||
1136 | dip->stream = &vp->channel.mc_head->video_stream; | 1115 | dip->stream = &vp->channel.mc_head->video_stream; |
1116 | dip->config = pvr2_config_mpeg; | ||
1117 | dip->minor_type = pvr2_v4l_type_video; | ||
1118 | nr_ptr = video_nr; | ||
1137 | break; | 1119 | break; |
1138 | case pvr2_config_vbi: | 1120 | case VFL_TYPE_VBI: |
1139 | v4l_type = VFL_TYPE_VBI; | 1121 | dip->config = pvr2_config_vbi; |
1140 | pvt = pvr2_v4l_type_vbi; | 1122 | dip->minor_type = pvr2_v4l_type_vbi; |
1123 | nr_ptr = vbi_nr; | ||
1141 | break; | 1124 | break; |
1142 | case pvr2_config_radio: | 1125 | case VFL_TYPE_RADIO: |
1143 | v4l_type = VFL_TYPE_RADIO; | 1126 | dip->config = pvr2_config_pcm; |
1144 | pvt = pvr2_v4l_type_radio; | 1127 | dip->minor_type = pvr2_v4l_type_radio; |
1128 | nr_ptr = radio_nr; | ||
1145 | break; | 1129 | break; |
1146 | default: | 1130 | default: |
1147 | /* Bail out (this should be impossible) */ | 1131 | /* Bail out (this should be impossible) */ |
@@ -1151,7 +1135,7 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1151 | } | 1135 | } |
1152 | 1136 | ||
1153 | /* radio device doesn 't need its own stream */ | 1137 | /* radio device doesn 't need its own stream */ |
1154 | if (!dip->stream && dip->config != pvr2_config_radio) { | 1138 | if (!dip->stream && dip->v4l_type == VFL_TYPE_GRABBER) { |
1155 | err("Failed to set up pvrusb2 v4l dev" | 1139 | err("Failed to set up pvrusb2 v4l dev" |
1156 | " due to missing stream instance"); | 1140 | " due to missing stream instance"); |
1157 | return; | 1141 | return; |
@@ -1162,46 +1146,22 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip, | |||
1162 | 1146 | ||
1163 | mindevnum = -1; | 1147 | mindevnum = -1; |
1164 | unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); | 1148 | unit_number = pvr2_hdw_get_unit_number(vp->channel.mc_head->hdw); |
1165 | if ((unit_number >= 0) && (unit_number < PVR_NUM)) { | 1149 | if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) { |
1166 | switch (v4l_type) { | 1150 | mindevnum = nr_ptr[unit_number]; |
1167 | case VFL_TYPE_VBI: | ||
1168 | mindevnum = vbi_nr[unit_number]; | ||
1169 | break; | ||
1170 | case VFL_TYPE_RADIO: | ||
1171 | mindevnum = radio_nr[unit_number]; | ||
1172 | break; | ||
1173 | case VFL_TYPE_GRABBER: | ||
1174 | default: | ||
1175 | mindevnum = video_nr[unit_number]; | ||
1176 | break; | ||
1177 | } | ||
1178 | } | 1151 | } |
1179 | if ((video_register_device(&dip->devbase, v4l_type, mindevnum) < 0) && | 1152 | if ((video_register_device(&dip->devbase, |
1180 | (video_register_device(&dip->devbase, v4l_type, -1) < 0)) { | 1153 | dip->v4l_type, mindevnum) < 0) && |
1154 | (video_register_device(&dip->devbase, | ||
1155 | dip->v4l_type, -1) < 0)) { | ||
1181 | err("Failed to register pvrusb2 v4l device"); | 1156 | err("Failed to register pvrusb2 v4l device"); |
1182 | } | 1157 | } |
1183 | switch (dip->config) { | 1158 | |
1184 | case pvr2_config_mpeg: | 1159 | printk(KERN_INFO "pvrusb2: registered device %s%u [%s]\n", |
1185 | printk(KERN_INFO "pvrusb2: registered device video%d [%s]\n", | 1160 | get_v4l_name(dip->v4l_type),dip->devbase.minor & 0x1f, |
1186 | dip->devbase.minor & 0x1f, | 1161 | pvr2_config_get_name(dip->config)); |
1187 | pvr2_config_get_name(dip->config)); | ||
1188 | break; | ||
1189 | case pvr2_config_radio: | ||
1190 | printk(KERN_INFO "pvrusb2: registered device radio%d [%s]\n", | ||
1191 | dip->devbase.minor & 0x1f, | ||
1192 | pvr2_config_get_name(dip->config)); | ||
1193 | break; | ||
1194 | case pvr2_config_vbi: | ||
1195 | printk(KERN_INFO "pvrusb2: registered device vbi%d [%s]\n", | ||
1196 | dip->devbase.minor & 0x1f, | ||
1197 | pvr2_config_get_name(dip->config)); | ||
1198 | break; | ||
1199 | default: | ||
1200 | break; | ||
1201 | } | ||
1202 | 1162 | ||
1203 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, | 1163 | pvr2_hdw_v4l_store_minor_number(vp->channel.mc_head->hdw, |
1204 | pvt,dip->devbase.minor); | 1164 | dip->minor_type,dip->devbase.minor); |
1205 | } | 1165 | } |
1206 | 1166 | ||
1207 | 1167 | ||
@@ -1228,8 +1188,8 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) | |||
1228 | vp->channel.check_func = pvr2_v4l2_internal_check; | 1188 | vp->channel.check_func = pvr2_v4l2_internal_check; |
1229 | 1189 | ||
1230 | /* register streams */ | 1190 | /* register streams */ |
1231 | pvr2_v4l2_dev_init(vp->dev_video,vp,pvr2_config_mpeg); | 1191 | pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER); |
1232 | pvr2_v4l2_dev_init(vp->dev_radio,vp,pvr2_config_radio); | 1192 | pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO); |
1233 | 1193 | ||
1234 | return vp; | 1194 | return vp; |
1235 | } | 1195 | } |