cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pvrusb2-ctrl.c (12903B)


      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
     14static 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. */
     39int 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. */
     46int 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. */
     71int 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 */
     83enum 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) */
     91int 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) */
    107int 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) */
    123int 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) */
    139int 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) */
    153int 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 */
    167const 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 */
    175const 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 */
    183int 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 */
    225int pvr2_ctrl_get_v4lid(struct pvr2_ctrl *cptr)
    226{
    227	if (!cptr) return 0;
    228	return cptr->info->v4l_id;
    229}
    230
    231
    232unsigned 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 */
    251int 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 */
    259int 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 */
    269int 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 */
    281int 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
    291static 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
    346static const char *boolNames[] = {
    347	"false",
    348	"true",
    349	"no",
    350	"yes",
    351};
    352
    353
    354static int parse_token(const char *ptr,unsigned int len,
    355		       int *valptr,
    356		       const char * const *names, unsigned int namecnt)
    357{
    358	unsigned int slen;
    359	unsigned int idx;
    360	*valptr = 0;
    361	if (!names) namecnt = 0;
    362	for (idx = 0; idx < namecnt; idx++) {
    363		if (!names[idx]) continue;
    364		slen = strlen(names[idx]);
    365		if (slen != len) continue;
    366		if (memcmp(names[idx],ptr,slen)) continue;
    367		*valptr = idx;
    368		return 0;
    369	}
    370	return kstrtoint(ptr, 0, valptr) ? -EINVAL : 1;
    371}
    372
    373
    374static int parse_mtoken(const char *ptr,unsigned int len,
    375			int *valptr,
    376			const char **names,int valid_bits)
    377{
    378	unsigned int slen;
    379	unsigned int idx;
    380	int msk;
    381	*valptr = 0;
    382	for (idx = 0, msk = 1; valid_bits; idx++, msk <<= 1) {
    383		if (!(msk & valid_bits)) continue;
    384		valid_bits &= ~msk;
    385		if (!names[idx]) continue;
    386		slen = strlen(names[idx]);
    387		if (slen != len) continue;
    388		if (memcmp(names[idx],ptr,slen)) continue;
    389		*valptr = msk;
    390		return 0;
    391	}
    392	return kstrtoint(ptr, 0, valptr);
    393}
    394
    395
    396static int parse_tlist(const char *ptr,unsigned int len,
    397		       int *maskptr,int *valptr,
    398		       const char **names,int valid_bits)
    399{
    400	unsigned int cnt;
    401	int mask,val,kv,mode,ret;
    402	mask = 0;
    403	val = 0;
    404	ret = 0;
    405	while (len) {
    406		cnt = 0;
    407		while ((cnt < len) &&
    408		       ((ptr[cnt] <= 32) ||
    409			(ptr[cnt] >= 127))) cnt++;
    410		ptr += cnt;
    411		len -= cnt;
    412		mode = 0;
    413		if ((*ptr == '-') || (*ptr == '+')) {
    414			mode = (*ptr == '-') ? -1 : 1;
    415			ptr++;
    416			len--;
    417		}
    418		cnt = 0;
    419		while (cnt < len) {
    420			if (ptr[cnt] <= 32) break;
    421			if (ptr[cnt] >= 127) break;
    422			cnt++;
    423		}
    424		if (!cnt) break;
    425		if (parse_mtoken(ptr,cnt,&kv,names,valid_bits)) {
    426			ret = -EINVAL;
    427			break;
    428		}
    429		ptr += cnt;
    430		len -= cnt;
    431		switch (mode) {
    432		case 0:
    433			mask = valid_bits;
    434			val |= kv;
    435			break;
    436		case -1:
    437			mask |= kv;
    438			val &= ~kv;
    439			break;
    440		case 1:
    441			mask |= kv;
    442			val |= kv;
    443			break;
    444		default:
    445			break;
    446		}
    447	}
    448	*maskptr = mask;
    449	*valptr = val;
    450	return ret;
    451}
    452
    453
    454/* Convert a symbolic value to a mask/value pair */
    455int pvr2_ctrl_sym_to_value(struct pvr2_ctrl *cptr,
    456			   const char *ptr,unsigned int len,
    457			   int *maskptr,int *valptr)
    458{
    459	int ret = -EINVAL;
    460	unsigned int cnt;
    461
    462	*maskptr = 0;
    463	*valptr = 0;
    464
    465	cnt = 0;
    466	while ((cnt < len) && ((ptr[cnt] <= 32) || (ptr[cnt] >= 127))) cnt++;
    467	len -= cnt; ptr += cnt;
    468	cnt = 0;
    469	while ((cnt < len) && ((ptr[len-(cnt+1)] <= 32) ||
    470			       (ptr[len-(cnt+1)] >= 127))) cnt++;
    471	len -= cnt;
    472
    473	if (!len) return -EINVAL;
    474
    475	LOCK_TAKE(cptr->hdw->big_lock); do {
    476		if (cptr->info->type == pvr2_ctl_int) {
    477			ret = parse_token(ptr,len,valptr,NULL,0);
    478			if (ret >= 0) {
    479				ret = pvr2_ctrl_range_check(cptr,*valptr);
    480			}
    481			*maskptr = ~0;
    482		} else if (cptr->info->type == pvr2_ctl_bool) {
    483			ret = parse_token(ptr,len,valptr,boolNames,
    484					  ARRAY_SIZE(boolNames));
    485			if (ret == 1) {
    486				*valptr = *valptr ? !0 : 0;
    487			} else if (ret == 0) {
    488				*valptr = (*valptr & 1) ? !0 : 0;
    489			}
    490			*maskptr = 1;
    491		} else if (cptr->info->type == pvr2_ctl_enum) {
    492			ret = parse_token(
    493				ptr,len,valptr,
    494				cptr->info->def.type_enum.value_names,
    495				cptr->info->def.type_enum.count);
    496			if (ret >= 0) {
    497				ret = pvr2_ctrl_range_check(cptr,*valptr);
    498			}
    499			*maskptr = ~0;
    500		} else if (cptr->info->type == pvr2_ctl_bitmask) {
    501			ret = parse_tlist(
    502				ptr,len,maskptr,valptr,
    503				cptr->info->def.type_bitmask.bit_names,
    504				cptr->info->def.type_bitmask.valid_bits);
    505		}
    506	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
    507	return ret;
    508}
    509
    510
    511/* Convert a given mask/val to a symbolic value */
    512int pvr2_ctrl_value_to_sym_internal(struct pvr2_ctrl *cptr,
    513				    int mask,int val,
    514				    char *buf,unsigned int maxlen,
    515				    unsigned int *len)
    516{
    517	int ret = -EINVAL;
    518
    519	*len = 0;
    520	if (cptr->info->type == pvr2_ctl_int) {
    521		*len = scnprintf(buf,maxlen,"%d",val);
    522		ret = 0;
    523	} else if (cptr->info->type == pvr2_ctl_bool) {
    524		*len = scnprintf(buf,maxlen,"%s",val ? "true" : "false");
    525		ret = 0;
    526	} else if (cptr->info->type == pvr2_ctl_enum) {
    527		const char * const *names;
    528		names = cptr->info->def.type_enum.value_names;
    529		if ((val >= 0) &&
    530		    (val < cptr->info->def.type_enum.count)) {
    531			if (names[val]) {
    532				*len = scnprintf(
    533					buf,maxlen,"%s",
    534					names[val]);
    535			} else {
    536				*len = 0;
    537			}
    538			ret = 0;
    539		}
    540	} else if (cptr->info->type == pvr2_ctl_bitmask) {
    541		*len = gen_bitmask_string(
    542			val & mask & cptr->info->def.type_bitmask.valid_bits,
    543			~0,!0,
    544			cptr->info->def.type_bitmask.bit_names,
    545			buf,maxlen);
    546	}
    547	return ret;
    548}
    549
    550
    551/* Convert a given mask/val to a symbolic value */
    552int pvr2_ctrl_value_to_sym(struct pvr2_ctrl *cptr,
    553			   int mask,int val,
    554			   char *buf,unsigned int maxlen,
    555			   unsigned int *len)
    556{
    557	int ret;
    558	LOCK_TAKE(cptr->hdw->big_lock); do {
    559		ret = pvr2_ctrl_value_to_sym_internal(cptr,mask,val,
    560						      buf,maxlen,len);
    561	} while(0); LOCK_GIVE(cptr->hdw->big_lock);
    562	return ret;
    563}