Merge tag 'for-5.11-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-2.6-microblaze.git] / drivers / media / usb / pvrusb2 / pvrusb2-ctrl.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
5  */
6
7 #include "pvrusb2-ctrl.h"
8 #include "pvrusb2-hdw-internal.h"
9 #include <linux/errno.h>
10 #include <linux/string.h>
11 #include <linux/mutex.h>
12
13
14 static int pvr2_ctrl_range_check(struct pvr2_ctrl *cptr,int val)
15 {
16         if (cptr->info->check_value) {
17                 if (!cptr->info->check_value(cptr,val)) return -ERANGE;
18         } else if (cptr->info->type == pvr2_ctl_enum) {
19                 if (val < 0) return -ERANGE;
20                 if (val >= cptr->info->def.type_enum.count) return -ERANGE;
21         } else {
22                 int lim;
23                 lim = cptr->info->def.type_int.min_value;
24                 if (cptr->info->get_min_value) {
25                         cptr->info->get_min_value(cptr,&lim);
26                 }
27                 if (val < lim) return -ERANGE;
28                 lim = cptr->info->def.type_int.max_value;
29                 if (cptr->info->get_max_value) {
30                         cptr->info->get_max_value(cptr,&lim);
31                 }
32                 if (val > lim) return -ERANGE;
33         }
34         return 0;
35 }
36
37
38 /* Set the given control. */
39 int pvr2_ctrl_set_value(struct pvr2_ctrl *cptr,int val)
40 {
41         return pvr2_ctrl_set_mask_value(cptr,~0,val);
42 }
43
44
45 /* Set/clear specific bits of the given control. */
46 int pvr2_ctrl_set_mask_value(struct pvr2_ctrl *cptr,int mask,int val)
47 {
48         int ret = 0;
49         if (!cptr) return -EINVAL;
50         LOCK_TAKE(cptr->hdw->big_lock); do {
51                 if (cptr->info->set_value) {
52                         if (cptr->info->type == pvr2_ctl_bitmask) {
53                                 mask &= cptr->info->def.type_bitmask.valid_bits;
54                         } else if ((cptr->info->type == pvr2_ctl_int)||
55                                    (cptr->info->type == pvr2_ctl_enum)) {
56                                 ret = pvr2_ctrl_range_check(cptr,val);
57                                 if (ret < 0) break;
58                         } else if (cptr->info->type != pvr2_ctl_bool) {
59                                 break;
60                         }
61                         ret = cptr->info->set_value(cptr,mask,val);
62                 } else {
63                         ret = -EPERM;
64                 }
65         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
66         return ret;
67 }
68
69
70 /* Get the current value of the given control. */
71 int pvr2_ctrl_get_value(struct pvr2_ctrl *cptr,int *valptr)
72 {
73         int ret = 0;
74         if (!cptr) return -EINVAL;
75         LOCK_TAKE(cptr->hdw->big_lock); do {
76                 ret = cptr->info->get_value(cptr,valptr);
77         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
78         return ret;
79 }
80
81
82 /* Retrieve control's type */
83 enum pvr2_ctl_type pvr2_ctrl_get_type(struct pvr2_ctrl *cptr)
84 {
85         if (!cptr) return pvr2_ctl_int;
86         return cptr->info->type;
87 }
88
89
90 /* Retrieve control's maximum value (int type) */
91 int pvr2_ctrl_get_max(struct pvr2_ctrl *cptr)
92 {
93         int ret = 0;
94         if (!cptr) return 0;
95         LOCK_TAKE(cptr->hdw->big_lock); do {
96                 if (cptr->info->get_max_value) {
97                         cptr->info->get_max_value(cptr,&ret);
98                 } else if (cptr->info->type == pvr2_ctl_int) {
99                         ret = cptr->info->def.type_int.max_value;
100                 }
101         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
102         return ret;
103 }
104
105
106 /* Retrieve control's minimum value (int type) */
107 int pvr2_ctrl_get_min(struct pvr2_ctrl *cptr)
108 {
109         int ret = 0;
110         if (!cptr) return 0;
111         LOCK_TAKE(cptr->hdw->big_lock); do {
112                 if (cptr->info->get_min_value) {
113                         cptr->info->get_min_value(cptr,&ret);
114                 } else if (cptr->info->type == pvr2_ctl_int) {
115                         ret = cptr->info->def.type_int.min_value;
116                 }
117         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
118         return ret;
119 }
120
121
122 /* Retrieve control's default value (any type) */
123 int pvr2_ctrl_get_def(struct pvr2_ctrl *cptr, int *valptr)
124 {
125         int ret = 0;
126         if (!cptr) return -EINVAL;
127         LOCK_TAKE(cptr->hdw->big_lock); do {
128                 if (cptr->info->get_def_value) {
129                         ret = cptr->info->get_def_value(cptr, valptr);
130                 } else {
131                         *valptr = cptr->info->default_value;
132                 }
133         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
134         return ret;
135 }
136
137
138 /* Retrieve control's enumeration count (enum only) */
139 int pvr2_ctrl_get_cnt(struct pvr2_ctrl *cptr)
140 {
141         int ret = 0;
142         if (!cptr) return 0;
143         LOCK_TAKE(cptr->hdw->big_lock); do {
144                 if (cptr->info->type == pvr2_ctl_enum) {
145                         ret = cptr->info->def.type_enum.count;
146                 }
147         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
148         return ret;
149 }
150
151
152 /* Retrieve control's valid mask bits (bit mask only) */
153 int pvr2_ctrl_get_mask(struct pvr2_ctrl *cptr)
154 {
155         int ret = 0;
156         if (!cptr) return 0;
157         LOCK_TAKE(cptr->hdw->big_lock); do {
158                 if (cptr->info->type == pvr2_ctl_bitmask) {
159                         ret = cptr->info->def.type_bitmask.valid_bits;
160                 }
161         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
162         return ret;
163 }
164
165
166 /* Retrieve the control's name */
167 const char *pvr2_ctrl_get_name(struct pvr2_ctrl *cptr)
168 {
169         if (!cptr) return NULL;
170         return cptr->info->name;
171 }
172
173
174 /* Retrieve the control's desc */
175 const char *pvr2_ctrl_get_desc(struct pvr2_ctrl *cptr)
176 {
177         if (!cptr) return NULL;
178         return cptr->info->desc;
179 }
180
181
182 /* Retrieve a control enumeration or bit mask value */
183 int pvr2_ctrl_get_valname(struct pvr2_ctrl *cptr,int val,
184                           char *bptr,unsigned int bmax,
185                           unsigned int *blen)
186 {
187         int ret = -EINVAL;
188         if (!cptr) return 0;
189         *blen = 0;
190         LOCK_TAKE(cptr->hdw->big_lock); do {
191                 if (cptr->info->type == pvr2_ctl_enum) {
192                         const char * const *names;
193                         names = cptr->info->def.type_enum.value_names;
194                         if (pvr2_ctrl_range_check(cptr,val) == 0) {
195                                 if (names[val]) {
196                                         *blen = scnprintf(
197                                                 bptr,bmax,"%s",
198                                                 names[val]);
199                                 } else {
200                                         *blen = 0;
201                                 }
202                                 ret = 0;
203                         }
204                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
205                         const char **names;
206                         unsigned int idx;
207                         int msk;
208                         names = cptr->info->def.type_bitmask.bit_names;
209                         val &= cptr->info->def.type_bitmask.valid_bits;
210                         for (idx = 0, msk = 1; val; idx++, msk <<= 1) {
211                                 if (val & msk) {
212                                         *blen = scnprintf(bptr,bmax,"%s",
213                                                           names[idx]);
214                                         ret = 0;
215                                         break;
216                                 }
217                         }
218                 }
219         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
220         return ret;
221 }
222
223
224 /* Return V4L ID for this control or zero if none */
225 int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
226 {
227         if (!cptr) return 0;
228         return cptr->info->v4l_id;
229 }
230
231
232 unsigned int pvr2_ctrl_get_v4lflags(struct pvr2_ctrl *cptr)
233 {
234         unsigned int flags = 0;
235
236         if (cptr->info->get_v4lflags) {
237                 flags = cptr->info->get_v4lflags(cptr);
238         }
239
240         if (cptr->info->set_value) {
241                 flags &= ~V4L2_CTRL_FLAG_READ_ONLY;
242         } else {
243                 flags |= V4L2_CTRL_FLAG_READ_ONLY;
244         }
245
246         return flags;
247 }
248
249
250 /* Return true if control is writable */
251 int pvr2_ctrl_is_writable(struct pvr2_ctrl *cptr)
252 {
253         if (!cptr) return 0;
254         return cptr->info->set_value != NULL;
255 }
256
257
258 /* Return true if control has custom symbolic representation */
259 int pvr2_ctrl_has_custom_symbols(struct pvr2_ctrl *cptr)
260 {
261         if (!cptr) return 0;
262         if (!cptr->info->val_to_sym) return 0;
263         if (!cptr->info->sym_to_val) return 0;
264         return !0;
265 }
266
267
268 /* Convert a given mask/val to a custom symbolic value */
269 int pvr2_ctrl_custom_value_to_sym(struct pvr2_ctrl *cptr,
270                                   int mask,int val,
271                                   char *buf,unsigned int maxlen,
272                                   unsigned int *len)
273 {
274         if (!cptr) return -EINVAL;
275         if (!cptr->info->val_to_sym) return -EINVAL;
276         return cptr->info->val_to_sym(cptr,mask,val,buf,maxlen,len);
277 }
278
279
280 /* Convert a symbolic value to a mask/value pair */
281 int pvr2_ctrl_custom_sym_to_value(struct pvr2_ctrl *cptr,
282                                   const char *buf,unsigned int len,
283                                   int *maskptr,int *valptr)
284 {
285         if (!cptr) return -EINVAL;
286         if (!cptr->info->sym_to_val) return -EINVAL;
287         return cptr->info->sym_to_val(cptr,buf,len,maskptr,valptr);
288 }
289
290
291 static unsigned int gen_bitmask_string(int msk,int val,int msk_only,
292                                        const char **names,
293                                        char *ptr,unsigned int len)
294 {
295         unsigned int idx;
296         long sm,um;
297         int spcFl;
298         unsigned int uc,cnt;
299         const char *idStr;
300
301         spcFl = 0;
302         uc = 0;
303         um = 0;
304         for (idx = 0, sm = 1; msk; idx++, sm <<= 1) {
305                 if (sm & msk) {
306                         msk &= ~sm;
307                         idStr = names[idx];
308                         if (idStr) {
309                                 cnt = scnprintf(ptr,len,"%s%s%s",
310                                                 (spcFl ? " " : ""),
311                                                 (msk_only ? "" :
312                                                  ((val & sm) ? "+" : "-")),
313                                                 idStr);
314                                 ptr += cnt; len -= cnt; uc += cnt;
315                                 spcFl = !0;
316                         } else {
317                                 um |= sm;
318                         }
319                 }
320         }
321         if (um) {
322                 if (msk_only) {
323                         cnt = scnprintf(ptr,len,"%s0x%lx",
324                                         (spcFl ? " " : ""),
325                                         um);
326                         ptr += cnt; len -= cnt; uc += cnt;
327                         spcFl = !0;
328                 } else if (um & val) {
329                         cnt = scnprintf(ptr,len,"%s+0x%lx",
330                                         (spcFl ? " " : ""),
331                                         um & val);
332                         ptr += cnt; len -= cnt; uc += cnt;
333                         spcFl = !0;
334                 } else if (um & ~val) {
335                         cnt = scnprintf(ptr,len,"%s+0x%lx",
336                                         (spcFl ? " " : ""),
337                                         um & ~val);
338                         ptr += cnt; len -= cnt; uc += cnt;
339                         spcFl = !0;
340                 }
341         }
342         return uc;
343 }
344
345
346 static const char *boolNames[] = {
347         "false",
348         "true",
349         "no",
350         "yes",
351 };
352
353
354 static int parse_token(const char *ptr,unsigned int len,
355                        int *valptr,
356                        const char * const *names, unsigned int namecnt)
357 {
358         char buf[33];
359         unsigned int slen;
360         unsigned int idx;
361         int negfl;
362         char *p2;
363         *valptr = 0;
364         if (!names) namecnt = 0;
365         for (idx = 0; idx < namecnt; idx++) {
366                 if (!names[idx]) continue;
367                 slen = strlen(names[idx]);
368                 if (slen != len) continue;
369                 if (memcmp(names[idx],ptr,slen)) continue;
370                 *valptr = idx;
371                 return 0;
372         }
373         negfl = 0;
374         if ((*ptr == '-') || (*ptr == '+')) {
375                 negfl = (*ptr == '-');
376                 ptr++; len--;
377         }
378         if (len >= sizeof(buf)) return -EINVAL;
379         memcpy(buf,ptr,len);
380         buf[len] = 0;
381         *valptr = simple_strtol(buf,&p2,0);
382         if (negfl) *valptr = -(*valptr);
383         if (*p2) return -EINVAL;
384         return 1;
385 }
386
387
388 static int parse_mtoken(const char *ptr,unsigned int len,
389                         int *valptr,
390                         const char **names,int valid_bits)
391 {
392         char buf[33];
393         unsigned int slen;
394         unsigned int idx;
395         char *p2;
396         int msk;
397         *valptr = 0;
398         for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
399                 if (!(msk & valid_bits)) continue;
400                 valid_bits &= ~msk;
401                 if (!names[idx]) continue;
402                 slen = strlen(names[idx]);
403                 if (slen != len) continue;
404                 if (memcmp(names[idx],ptr,slen)) continue;
405                 *valptr = msk;
406                 return 0;
407         }
408         if (len >= sizeof(buf)) return -EINVAL;
409         memcpy(buf,ptr,len);
410         buf[len] = 0;
411         *valptr = simple_strtol(buf,&p2,0);
412         if (*p2) return -EINVAL;
413         return 0;
414 }
415
416
417 static int parse_tlist(const char *ptr,unsigned int len,
418                        int *maskptr,int *valptr,
419                        const char **names,int valid_bits)
420 {
421         unsigned int cnt;
422         int mask,val,kv,mode,ret;
423         mask = 0;
424         val = 0;
425         ret = 0;
426         while (len) {
427                 cnt = 0;
428                 while ((cnt < len) &&
429                        ((ptr[cnt] <= 32) ||
430                         (ptr[cnt] >= 127))) cnt++;
431                 ptr += cnt;
432                 len -= cnt;
433                 mode = 0;
434                 if ((*ptr == '-') || (*ptr == '+')) {
435                         mode = (*ptr == '-') ? -1 : 1;
436                         ptr++;
437                         len--;
438                 }
439                 cnt = 0;
440                 while (cnt < len) {
441                         if (ptr[cnt] <= 32) break;
442                         if (ptr[cnt] >= 127) break;
443                         cnt++;
444                 }
445                 if (!cnt) break;
446                 if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
447                         ret = -EINVAL;
448                         break;
449                 }
450                 ptr += cnt;
451                 len -= cnt;
452                 switch (mode) {
453                 case 0:
454                         mask = valid_bits;
455                         val |= kv;
456                         break;
457                 case -1:
458                         mask |= kv;
459                         val &= ~kv;
460                         break;
461                 case 1:
462                         mask |= kv;
463                         val |= kv;
464                         break;
465                 default:
466                         break;
467                 }
468         }
469         *maskptr = mask;
470         *valptr = val;
471         return ret;
472 }
473
474
475 /* Convert a symbolic value to a mask/value pair */
476 int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
477                            const char *ptr,unsigned int len,
478                            int *maskptr,int *valptr)
479 {
480         int ret = -EINVAL;
481         unsigned int cnt;
482
483         *maskptr = 0;
484         *valptr = 0;
485
486         cnt = 0;
487         while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
488         len -= cnt; ptr += cnt;
489         cnt = 0;
490         while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
491                                (ptr[len-(cnt+1)] >= 127))) cnt++;
492         len -= cnt;
493
494         if (!len) return -EINVAL;
495
496         LOCK_TAKE(cptr->hdw->big_lock); do {
497                 if (cptr->info->type == pvr2_ctl_int) {
498                         ret = parse_token(ptr,len,valptr,NULL,0);
499                         if (ret >= 0) {
500                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
501                         }
502                         *maskptr = ~0;
503                 } else if (cptr->info->type == pvr2_ctl_bool) {
504                         ret = parse_token(ptr,len,valptr,boolNames,
505                                           ARRAY_SIZE(boolNames));
506                         if (ret == 1) {
507                                 *valptr = *valptr ? !0 : 0;
508                         } else if (ret == 0) {
509                                 *valptr = (*valptr & 1) ? !0 : 0;
510                         }
511                         *maskptr = 1;
512                 } else if (cptr->info->type == pvr2_ctl_enum) {
513                         ret = parse_token(
514                                 ptr,len,valptr,
515                                 cptr->info->def.type_enum.value_names,
516                                 cptr->info->def.type_enum.count);
517                         if (ret >= 0) {
518                                 ret = pvr2_ctrl_range_check(cptr,*valptr);
519                         }
520                         *maskptr = ~0;
521                 } else if (cptr->info->type == pvr2_ctl_bitmask) {
522                         ret = parse_tlist(
523                                 ptr,len,maskptr,valptr,
524                                 cptr->info->def.type_bitmask.bit_names,
525                                 cptr->info->def.type_bitmask.valid_bits);
526                 }
527         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
528         return ret;
529 }
530
531
532 /* Convert a given mask/val to a symbolic value */
533 int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
534                                     int mask,int val,
535                                     char *buf,unsigned int maxlen,
536                                     unsigned int *len)
537 {
538         int ret = -EINVAL;
539
540         *len = 0;
541         if (cptr->info->type == pvr2_ctl_int) {
542                 *len = scnprintf(buf,maxlen,"%d",val);
543                 ret = 0;
544         } else if (cptr->info->type == pvr2_ctl_bool) {
545                 *len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
546                 ret = 0;
547         } else if (cptr->info->type == pvr2_ctl_enum) {
548                 const char * const *names;
549                 names = cptr->info->def.type_enum.value_names;
550                 if ((val >= 0) &&
551                     (val < cptr->info->def.type_enum.count)) {
552                         if (names[val]) {
553                                 *len = scnprintf(
554                                         buf,maxlen,"%s",
555                                         names[val]);
556                         } else {
557                                 *len = 0;
558                         }
559                         ret = 0;
560                 }
561         } else if (cptr->info->type == pvr2_ctl_bitmask) {
562                 *len = gen_bitmask_string(
563                         val & mask & cptr->info->def.type_bitmask.valid_bits,
564                         ~0,!0,
565                         cptr->info->def.type_bitmask.bit_names,
566                         buf,maxlen);
567         }
568         return ret;
569 }
570
571
572 /* Convert a given mask/val to a symbolic value */
573 int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
574                            int mask,int val,
575                            char *buf,unsigned int maxlen,
576                            unsigned int *len)
577 {
578         int ret;
579         LOCK_TAKE(cptr->hdw->big_lock); do {
580                 ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
581                                                       buf,maxlen,len);
582         } while(0); LOCK_GIVE(cptr->hdw->big_lock);
583         return ret;
584 }