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 | /** |
