diff options
author | Steven Toth <stoth@linuxtv.org> | 2008-09-11 09:23:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-12 07:37:04 -0400 |
commit | e7fee0f3aa111d42cdcfc1470cfdc21dde0cdbe2 (patch) | |
tree | fedd63397870c4f97b26176ed3b7e2d660d77957 | |
parent | 56f0680a28397f4b412fc14f60ac380b910ee328 (diff) |
V4L/DVB (8996): S2API: typedefs replaced, _SEQ_'s removed, fixed 16 command arrays replaced
After discussion the following changes were made:
1. Removed the typedefs in frontend.h, use structures.
2. In the frontend.h, remove the 16 command limit on the API and
switch to a flexible variable length API. For practical reasons
a #define limits this to 64, this should be discussed.
3. Changed dvb-core ioctl handing to deal with variable sequences
of commands.
tune-v0.0.3.c is required to use this API, it contains the interface changes.
Signed-off-by: Steven Toth <stoth@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.c | 83 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-core/dvb_frontend.h | 4 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/cx24116.c | 2 | ||||
-rw-r--r-- | include/linux/dvb/frontend.h | 27 |
4 files changed, 63 insertions, 53 deletions
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 9c4761506d2d..763da968236f 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c | |||
@@ -756,29 +756,14 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, | |||
756 | } | 756 | } |
757 | 757 | ||
758 | struct dtv_cmds_h dtv_cmds[] = { | 758 | struct dtv_cmds_h dtv_cmds[] = { |
759 | [DTV_SEQ_UNDEFINED] = { | 759 | [DTV_TUNE] = { |
760 | .name = "DTV_SEQ_UNDEFINED", | 760 | .name = "DTV_TUNE", |
761 | .cmd = DTV_SEQ_UNDEFINED, | 761 | .cmd = DTV_TUNE, |
762 | .set = 1, | 762 | .set = 1, |
763 | }, | 763 | }, |
764 | [DTV_SEQ_START] = { | 764 | [DTV_CLEAR] = { |
765 | .name = "DTV_SEQ_START", | 765 | .name = "DTV_CLEAR", |
766 | .cmd = DTV_SEQ_START, | 766 | .cmd = DTV_CLEAR, |
767 | .set = 1, | ||
768 | }, | ||
769 | [DTV_SEQ_CONTINUE] = { | ||
770 | .name = "DTV_SEQ_CONTINUE", | ||
771 | .cmd = DTV_SEQ_CONTINUE, | ||
772 | .set = 1, | ||
773 | }, | ||
774 | [DTV_SEQ_COMPLETE] = { | ||
775 | .name = "DTV_SEQ_COMPLETE", | ||
776 | .cmd = DTV_SEQ_COMPLETE, | ||
777 | .set = 1, | ||
778 | }, | ||
779 | [DTV_SEQ_TERMINATE] = { | ||
780 | .name = "DTV_SEQ_TERMINATE", | ||
781 | .cmd = DTV_SEQ_TERMINATE, | ||
782 | .set = 1, | 767 | .set = 1, |
783 | }, | 768 | }, |
784 | 769 | ||
@@ -974,7 +959,7 @@ struct dtv_cmds_h dtv_cmds[] = { | |||
974 | }, | 959 | }, |
975 | }; | 960 | }; |
976 | 961 | ||
977 | void dtv_property_dump(dtv_property_t *tvp) | 962 | void dtv_property_dump(struct dtv_property *tvp) |
978 | { | 963 | { |
979 | int i; | 964 | int i; |
980 | 965 | ||
@@ -1044,6 +1029,7 @@ int dtv_property_cache_submit(struct dvb_frontend *fe) | |||
1044 | 1029 | ||
1045 | /* For legacy delivery systems we don't need the delivery_system to be specified */ | 1030 | /* For legacy delivery systems we don't need the delivery_system to be specified */ |
1046 | if(is_legacy_delivery_system(c->delivery_system)) { | 1031 | if(is_legacy_delivery_system(c->delivery_system)) { |
1032 | printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation); | ||
1047 | switch(c->modulation) { | 1033 | switch(c->modulation) { |
1048 | case QPSK: | 1034 | case QPSK: |
1049 | printk("%s() Preparing QPSK req\n", __FUNCTION__); | 1035 | printk("%s() Preparing QPSK req\n", __FUNCTION__); |
@@ -1161,7 +1147,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, | |||
1161 | static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | 1147 | static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, |
1162 | unsigned int cmd, void *parg); | 1148 | unsigned int cmd, void *parg); |
1163 | 1149 | ||
1164 | int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, | 1150 | int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp, |
1165 | struct inode *inode, struct file *file) | 1151 | struct inode *inode, struct file *file) |
1166 | { | 1152 | { |
1167 | int r = 0; | 1153 | int r = 0; |
@@ -1170,23 +1156,22 @@ int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, | |||
1170 | dtv_property_dump(tvp); | 1156 | dtv_property_dump(tvp); |
1171 | 1157 | ||
1172 | switch(tvp->cmd) { | 1158 | switch(tvp->cmd) { |
1173 | case DTV_SEQ_START: | 1159 | case DTV_CLEAR: |
1174 | case DTV_SEQ_TERMINATE: | ||
1175 | /* Reset a cache of data specific to the frontend here. This does | 1160 | /* Reset a cache of data specific to the frontend here. This does |
1176 | * not effect hardware. | 1161 | * not effect hardware. |
1177 | */ | 1162 | */ |
1178 | printk("%s() Flushing property cache\n", __FUNCTION__); | 1163 | printk("%s() Flushing property cache\n", __FUNCTION__); |
1179 | memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); | 1164 | memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); |
1180 | fe->dtv_property_cache.state = DTV_SEQ_START; | 1165 | fe->dtv_property_cache.state = tvp->cmd; |
1181 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; | 1166 | fe->dtv_property_cache.delivery_system = SYS_UNDEFINED; |
1182 | break; | 1167 | break; |
1183 | case DTV_SEQ_COMPLETE: | 1168 | case DTV_TUNE: |
1184 | /* interpret the cache of data, build either a traditional frontend | 1169 | /* interpret the cache of data, build either a traditional frontend |
1185 | * tunerequest and submit it to a subset of the ioctl handler, | 1170 | * tunerequest and submit it to a subset of the ioctl handler, |
1186 | * or, call a new undefined method on the frontend to deal with | 1171 | * or, call a new undefined method on the frontend to deal with |
1187 | * all new tune requests. | 1172 | * all new tune requests. |
1188 | */ | 1173 | */ |
1189 | fe->dtv_property_cache.state = DTV_SEQ_COMPLETE; | 1174 | fe->dtv_property_cache.state = tvp->cmd; |
1190 | printk("%s() Finalised property cache\n", __FUNCTION__); | 1175 | printk("%s() Finalised property cache\n", __FUNCTION__); |
1191 | r |= dtv_property_cache_submit(fe); | 1176 | r |= dtv_property_cache_submit(fe); |
1192 | r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, | 1177 | r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, |
@@ -1344,30 +1329,48 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file, | |||
1344 | struct dvb_device *dvbdev = file->private_data; | 1329 | struct dvb_device *dvbdev = file->private_data; |
1345 | struct dvb_frontend *fe = dvbdev->priv; | 1330 | struct dvb_frontend *fe = dvbdev->priv; |
1346 | int err = -EOPNOTSUPP; | 1331 | int err = -EOPNOTSUPP; |
1347 | dtv_property_t *tvp; | 1332 | |
1333 | struct dtv_properties *tvps = NULL; | ||
1334 | struct dtv_property *tvp = NULL; | ||
1335 | int i; | ||
1348 | 1336 | ||
1349 | dprintk("%s\n", __func__); | 1337 | dprintk("%s\n", __func__); |
1350 | 1338 | ||
1351 | if(cmd == FE_SET_PROPERTY) { | 1339 | if(cmd == FE_SET_PROPERTY) { |
1352 | printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); | 1340 | printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); |
1353 | 1341 | ||
1354 | /* TODO: basic property validation here */ | 1342 | tvps = (struct dtv_properties __user *)parg; |
1355 | 1343 | ||
1356 | /* TODO: ioctl userdata out of range check here */ | 1344 | printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num); |
1357 | tvp = parg; | 1345 | printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props); |
1358 | while(tvp->cmd != DTV_SEQ_UNDEFINED) { | 1346 | |
1359 | dtv_property_process(fe, tvp, inode, file); | 1347 | /* Put an arbitrary limit on the number of messages that can |
1360 | if( (tvp->cmd == DTV_SEQ_TERMINATE) || (tvp->cmd == DTV_SEQ_COMPLETE) ) | 1348 | * be sent at once */ |
1361 | break; | 1349 | if (tvps->num > DTV_IOCTL_MAX_MSGS) |
1362 | tvp++; | 1350 | return -EINVAL; |
1351 | |||
1352 | tvp = (struct dtv_property *) kmalloc(tvps->num * | ||
1353 | sizeof(struct dtv_property), GFP_KERNEL); | ||
1354 | if (!tvp) { | ||
1355 | err = -ENOMEM; | ||
1356 | goto out; | ||
1363 | } | 1357 | } |
1364 | 1358 | ||
1365 | if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { | 1359 | if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) { |
1360 | err = -EFAULT; | ||
1361 | goto out; | ||
1362 | } | ||
1363 | |||
1364 | for (i = 0; i < tvps->num; i++) | ||
1365 | dtv_property_process(fe, tvp + i, inode, file); | ||
1366 | |||
1367 | if(fe->dtv_property_cache.state == DTV_TUNE) { | ||
1366 | printk("%s() Property cache is full, tuning\n", __FUNCTION__); | 1368 | printk("%s() Property cache is full, tuning\n", __FUNCTION__); |
1367 | } | 1369 | } |
1368 | err = 0; | 1370 | err = 0; |
1369 | } | 1371 | } |
1370 | 1372 | out: | |
1373 | kfree(tvp); | ||
1371 | return err; | 1374 | return err; |
1372 | } | 1375 | } |
1373 | 1376 | ||
@@ -1545,7 +1548,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, | |||
1545 | case FE_SET_FRONTEND: { | 1548 | case FE_SET_FRONTEND: { |
1546 | struct dvb_frontend_tune_settings fetunesettings; | 1549 | struct dvb_frontend_tune_settings fetunesettings; |
1547 | 1550 | ||
1548 | if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) { | 1551 | if(fe->dtv_property_cache.state == DTV_TUNE) { |
1549 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { | 1552 | if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) { |
1550 | err = -EINVAL; | 1553 | err = -EINVAL; |
1551 | break; | 1554 | break; |
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h index f376f281cde2..85d30201a695 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.h +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h | |||
@@ -170,8 +170,8 @@ struct dvb_frontend_ops { | |||
170 | struct dvb_tuner_ops tuner_ops; | 170 | struct dvb_tuner_ops tuner_ops; |
171 | struct analog_demod_ops analog_ops; | 171 | struct analog_demod_ops analog_ops; |
172 | 172 | ||
173 | int (*set_property)(struct dvb_frontend* fe, dtv_property_t* tvp); | 173 | int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp); |
174 | int (*get_property)(struct dvb_frontend* fe, dtv_property_t* tvp); | 174 | int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp); |
175 | int (*set_params)(struct dvb_frontend* fe); | 175 | int (*set_params)(struct dvb_frontend* fe); |
176 | }; | 176 | }; |
177 | 177 | ||
diff --git a/drivers/media/dvb/frontends/cx24116.c b/drivers/media/dvb/frontends/cx24116.c index f150fa24ff9f..9f93930a2594 100644 --- a/drivers/media/dvb/frontends/cx24116.c +++ b/drivers/media/dvb/frontends/cx24116.c | |||
@@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe) | |||
796 | return cx24116_diseqc_init(fe); | 796 | return cx24116_diseqc_init(fe); |
797 | } | 797 | } |
798 | 798 | ||
799 | static int cx24116_set_property(struct dvb_frontend *fe, dtv_property_t* tvp) | 799 | static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp) |
800 | { | 800 | { |
801 | dprintk("%s(..)\n", __func__); | 801 | dprintk("%s(..)\n", __func__); |
802 | return 0; | 802 | return 0; |
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h index aeace74b5366..f667bf377a7b 100644 --- a/include/linux/dvb/frontend.h +++ b/include/linux/dvb/frontend.h | |||
@@ -251,11 +251,8 @@ struct dvb_frontend_event { | |||
251 | * binary compatability. | 251 | * binary compatability. |
252 | */ | 252 | */ |
253 | typedef enum dtv_cmd_types { | 253 | typedef enum dtv_cmd_types { |
254 | DTV_SEQ_UNDEFINED, | 254 | DTV_TUNE, |
255 | DTV_SEQ_START, | 255 | DTV_CLEAR, |
256 | DTV_SEQ_CONTINUE, | ||
257 | DTV_SEQ_COMPLETE, | ||
258 | DTV_SEQ_TERMINATE, | ||
259 | 256 | ||
260 | DTV_SET_FREQUENCY, | 257 | DTV_SET_FREQUENCY, |
261 | DTV_SET_MODULATION, | 258 | DTV_SET_MODULATION, |
@@ -348,22 +345,32 @@ struct dtv_cmds_h { | |||
348 | __u32 reserved:30; /* Align */ | 345 | __u32 reserved:30; /* Align */ |
349 | }; | 346 | }; |
350 | 347 | ||
351 | typedef struct { | 348 | struct dtv_property { |
352 | __u32 cmd; | 349 | __u32 cmd; |
350 | __u32 reserved[3]; | ||
353 | union { | 351 | union { |
352 | __s32 valuemin; | ||
353 | __s32 valuemax; | ||
354 | __u32 data; | 354 | __u32 data; |
355 | struct { | 355 | struct { |
356 | __u8 data[32]; | 356 | __u8 data[32]; |
357 | __u32 len; | 357 | __u32 len; |
358 | __u32 reserved1[3]; | ||
359 | void *reserved2; | ||
358 | } buffer; | 360 | } buffer; |
359 | } u; | 361 | } u; |
360 | } dtv_property_t; | 362 | } __attribute__ ((packed)); |
361 | 363 | ||
362 | /* No more than 16 properties during any given ioctl */ | 364 | /* No more than 16 properties during any given ioctl */ |
363 | typedef dtv_property_t dtv_properties_t[16]; | 365 | struct dtv_properties { |
366 | __u32 num; | ||
367 | struct dtv_property *props; | ||
368 | }; | ||
369 | |||
370 | #define DTV_IOCTL_MAX_MSGS 64 | ||
364 | 371 | ||
365 | #define FE_SET_PROPERTY _IOW('o', 82, dtv_properties_t) | 372 | #define FE_SET_PROPERTY _IOW('o', 82, struct dtv_properties) |
366 | #define FE_GET_PROPERTY _IOR('o', 83, dtv_properties_t) | 373 | #define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties) |
367 | 374 | ||
368 | 375 | ||
369 | /** | 376 | /** |