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