root/drivers/media/usb/pvrusb2/pvrusb2-std.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_std_name
  2. pvr2_std_str_to_id
  3. pvr2_std_id_to_str
  4. match_std
  5. pvr2_std_fill
  6. pvr2_std_create_enum
  7. pvr2_std_get_usable

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *
   4  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
   5  */
   6 
   7 #include "pvrusb2-std.h"
   8 #include "pvrusb2-debug.h"
   9 #include <asm/string.h>
  10 #include <linux/slab.h>
  11 
  12 struct std_name {
  13         const char *name;
  14         v4l2_std_id id;
  15 };
  16 
  17 
  18 #define CSTD_PAL \
  19         (V4L2_STD_PAL_B| \
  20          V4L2_STD_PAL_B1| \
  21          V4L2_STD_PAL_G| \
  22          V4L2_STD_PAL_H| \
  23          V4L2_STD_PAL_I| \
  24          V4L2_STD_PAL_D| \
  25          V4L2_STD_PAL_D1| \
  26          V4L2_STD_PAL_K| \
  27          V4L2_STD_PAL_M| \
  28          V4L2_STD_PAL_N| \
  29          V4L2_STD_PAL_Nc| \
  30          V4L2_STD_PAL_60)
  31 
  32 #define CSTD_NTSC \
  33         (V4L2_STD_NTSC_M| \
  34          V4L2_STD_NTSC_M_JP| \
  35          V4L2_STD_NTSC_M_KR| \
  36          V4L2_STD_NTSC_443)
  37 
  38 #define CSTD_ATSC \
  39         (V4L2_STD_ATSC_8_VSB| \
  40          V4L2_STD_ATSC_16_VSB)
  41 
  42 #define CSTD_SECAM \
  43         (V4L2_STD_SECAM_B| \
  44          V4L2_STD_SECAM_D| \
  45          V4L2_STD_SECAM_G| \
  46          V4L2_STD_SECAM_H| \
  47          V4L2_STD_SECAM_K| \
  48          V4L2_STD_SECAM_K1| \
  49          V4L2_STD_SECAM_L| \
  50          V4L2_STD_SECAM_LC)
  51 
  52 #define TSTD_B   (V4L2_STD_PAL_B|V4L2_STD_SECAM_B)
  53 #define TSTD_B1  (V4L2_STD_PAL_B1)
  54 #define TSTD_D   (V4L2_STD_PAL_D|V4L2_STD_SECAM_D)
  55 #define TSTD_D1  (V4L2_STD_PAL_D1)
  56 #define TSTD_G   (V4L2_STD_PAL_G|V4L2_STD_SECAM_G)
  57 #define TSTD_H   (V4L2_STD_PAL_H|V4L2_STD_SECAM_H)
  58 #define TSTD_I   (V4L2_STD_PAL_I)
  59 #define TSTD_K   (V4L2_STD_PAL_K|V4L2_STD_SECAM_K)
  60 #define TSTD_K1  (V4L2_STD_SECAM_K1)
  61 #define TSTD_L   (V4L2_STD_SECAM_L)
  62 #define TSTD_M   (V4L2_STD_PAL_M|V4L2_STD_NTSC_M)
  63 #define TSTD_N   (V4L2_STD_PAL_N)
  64 #define TSTD_Nc  (V4L2_STD_PAL_Nc)
  65 #define TSTD_60  (V4L2_STD_PAL_60)
  66 
  67 #define CSTD_ALL (CSTD_PAL|CSTD_NTSC|CSTD_ATSC|CSTD_SECAM)
  68 
  69 /* Mapping of standard bits to color system */
  70 static const struct std_name std_groups[] = {
  71         {"PAL",CSTD_PAL},
  72         {"NTSC",CSTD_NTSC},
  73         {"SECAM",CSTD_SECAM},
  74         {"ATSC",CSTD_ATSC},
  75 };
  76 
  77 /* Mapping of standard bits to modulation system */
  78 static const struct std_name std_items[] = {
  79         {"B",TSTD_B},
  80         {"B1",TSTD_B1},
  81         {"D",TSTD_D},
  82         {"D1",TSTD_D1},
  83         {"G",TSTD_G},
  84         {"H",TSTD_H},
  85         {"I",TSTD_I},
  86         {"K",TSTD_K},
  87         {"K1",TSTD_K1},
  88         {"L",TSTD_L},
  89         {"LC",V4L2_STD_SECAM_LC},
  90         {"M",TSTD_M},
  91         {"Mj",V4L2_STD_NTSC_M_JP},
  92         {"443",V4L2_STD_NTSC_443},
  93         {"Mk",V4L2_STD_NTSC_M_KR},
  94         {"N",TSTD_N},
  95         {"Nc",TSTD_Nc},
  96         {"60",TSTD_60},
  97         {"8VSB",V4L2_STD_ATSC_8_VSB},
  98         {"16VSB",V4L2_STD_ATSC_16_VSB},
  99 };
 100 
 101 
 102 // Search an array of std_name structures and return a pointer to the
 103 // element with the matching name.
 104 static const struct std_name *find_std_name(const struct std_name *arrPtr,
 105                                             unsigned int arrSize,
 106                                             const char *bufPtr,
 107                                             unsigned int bufSize)
 108 {
 109         unsigned int idx;
 110         const struct std_name *p;
 111         for (idx = 0; idx < arrSize; idx++) {
 112                 p = arrPtr + idx;
 113                 if (strlen(p->name) != bufSize) continue;
 114                 if (!memcmp(bufPtr,p->name,bufSize)) return p;
 115         }
 116         return NULL;
 117 }
 118 
 119 
 120 int pvr2_std_str_to_id(v4l2_std_id *idPtr,const char *bufPtr,
 121                        unsigned int bufSize)
 122 {
 123         v4l2_std_id id = 0;
 124         v4l2_std_id cmsk = 0;
 125         v4l2_std_id t;
 126         int mMode = 0;
 127         unsigned int cnt;
 128         char ch;
 129         const struct std_name *sp;
 130 
 131         while (bufSize) {
 132                 if (!mMode) {
 133                         cnt = 0;
 134                         while ((cnt < bufSize) && (bufPtr[cnt] != '-')) cnt++;
 135                         if (cnt >= bufSize) return 0; // No more characters
 136                         sp = find_std_name(std_groups, ARRAY_SIZE(std_groups),
 137                                            bufPtr,cnt);
 138                         if (!sp) return 0; // Illegal color system name
 139                         cnt++;
 140                         bufPtr += cnt;
 141                         bufSize -= cnt;
 142                         mMode = !0;
 143                         cmsk = sp->id;
 144                         continue;
 145                 }
 146                 cnt = 0;
 147                 while (cnt < bufSize) {
 148                         ch = bufPtr[cnt];
 149                         if (ch == ';') {
 150                                 mMode = 0;
 151                                 break;
 152                         }
 153                         if (ch == '/') break;
 154                         cnt++;
 155                 }
 156                 sp = find_std_name(std_items, ARRAY_SIZE(std_items),
 157                                    bufPtr,cnt);
 158                 if (!sp) return 0; // Illegal modulation system ID
 159                 t = sp->id & cmsk;
 160                 if (!t) return 0; // Specific color + modulation system illegal
 161                 id |= t;
 162                 if (cnt < bufSize) cnt++;
 163                 bufPtr += cnt;
 164                 bufSize -= cnt;
 165         }
 166 
 167         if (idPtr) *idPtr = id;
 168         return !0;
 169 }
 170 
 171 
 172 unsigned int pvr2_std_id_to_str(char *bufPtr, unsigned int bufSize,
 173                                 v4l2_std_id id)
 174 {
 175         unsigned int idx1,idx2;
 176         const struct std_name *ip,*gp;
 177         int gfl,cfl;
 178         unsigned int c1,c2;
 179         cfl = 0;
 180         c1 = 0;
 181         for (idx1 = 0; idx1 < ARRAY_SIZE(std_groups); idx1++) {
 182                 gp = std_groups + idx1;
 183                 gfl = 0;
 184                 for (idx2 = 0; idx2 < ARRAY_SIZE(std_items); idx2++) {
 185                         ip = std_items + idx2;
 186                         if (!(gp->id & ip->id & id)) continue;
 187                         if (!gfl) {
 188                                 if (cfl) {
 189                                         c2 = scnprintf(bufPtr,bufSize,";");
 190                                         c1 += c2;
 191                                         bufSize -= c2;
 192                                         bufPtr += c2;
 193                                 }
 194                                 cfl = !0;
 195                                 c2 = scnprintf(bufPtr,bufSize,
 196                                                "%s-",gp->name);
 197                                 gfl = !0;
 198                         } else {
 199                                 c2 = scnprintf(bufPtr,bufSize,"/");
 200                         }
 201                         c1 += c2;
 202                         bufSize -= c2;
 203                         bufPtr += c2;
 204                         c2 = scnprintf(bufPtr,bufSize,
 205                                        ip->name);
 206                         c1 += c2;
 207                         bufSize -= c2;
 208                         bufPtr += c2;
 209                 }
 210         }
 211         return c1;
 212 }
 213 
 214 
 215 // Template data for possible enumerated video standards.  Here we group
 216 // standards which share common frame rates and resolution.
 217 static struct v4l2_standard generic_standards[] = {
 218         {
 219                 .id             = (TSTD_B|TSTD_B1|
 220                                    TSTD_D|TSTD_D1|
 221                                    TSTD_G|
 222                                    TSTD_H|
 223                                    TSTD_I|
 224                                    TSTD_K|TSTD_K1|
 225                                    TSTD_L|
 226                                    V4L2_STD_SECAM_LC |
 227                                    TSTD_N|TSTD_Nc),
 228                 .frameperiod    =
 229                 {
 230                         .numerator  = 1,
 231                         .denominator= 25
 232                 },
 233                 .framelines     = 625,
 234                 .reserved       = {0,0,0,0}
 235         }, {
 236                 .id             = (TSTD_M|
 237                                    V4L2_STD_NTSC_M_JP|
 238                                    V4L2_STD_NTSC_M_KR),
 239                 .frameperiod    =
 240                 {
 241                         .numerator  = 1001,
 242                         .denominator= 30000
 243                 },
 244                 .framelines     = 525,
 245                 .reserved       = {0,0,0,0}
 246         }, { // This is a total wild guess
 247                 .id             = (TSTD_60),
 248                 .frameperiod    =
 249                 {
 250                         .numerator  = 1001,
 251                         .denominator= 30000
 252                 },
 253                 .framelines     = 525,
 254                 .reserved       = {0,0,0,0}
 255         }, { // This is total wild guess
 256                 .id             = V4L2_STD_NTSC_443,
 257                 .frameperiod    =
 258                 {
 259                         .numerator  = 1001,
 260                         .denominator= 30000
 261                 },
 262                 .framelines     = 525,
 263                 .reserved       = {0,0,0,0}
 264         }
 265 };
 266 
 267 static struct v4l2_standard *match_std(v4l2_std_id id)
 268 {
 269         unsigned int idx;
 270         for (idx = 0; idx < ARRAY_SIZE(generic_standards); idx++) {
 271                 if (generic_standards[idx].id & id) {
 272                         return generic_standards + idx;
 273                 }
 274         }
 275         return NULL;
 276 }
 277 
 278 static int pvr2_std_fill(struct v4l2_standard *std,v4l2_std_id id)
 279 {
 280         struct v4l2_standard *template;
 281         int idx;
 282         unsigned int bcnt;
 283         template = match_std(id);
 284         if (!template) return 0;
 285         idx = std->index;
 286         memcpy(std,template,sizeof(*template));
 287         std->index = idx;
 288         std->id = id;
 289         bcnt = pvr2_std_id_to_str(std->name,sizeof(std->name)-1,id);
 290         std->name[bcnt] = 0;
 291         pvr2_trace(PVR2_TRACE_STD,"Set up standard idx=%u name=%s",
 292                    std->index,std->name);
 293         return !0;
 294 }
 295 
 296 /* These are special cases of combined standards that we should enumerate
 297    separately if the component pieces are present. */
 298 static v4l2_std_id std_mixes[] = {
 299         V4L2_STD_PAL_B | V4L2_STD_PAL_G,
 300         V4L2_STD_PAL_D | V4L2_STD_PAL_K,
 301         V4L2_STD_SECAM_B | V4L2_STD_SECAM_G,
 302         V4L2_STD_SECAM_D | V4L2_STD_SECAM_K,
 303 };
 304 
 305 struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
 306                                            v4l2_std_id id)
 307 {
 308         unsigned int std_cnt = 0;
 309         unsigned int idx,bcnt,idx2;
 310         v4l2_std_id idmsk,cmsk,fmsk;
 311         struct v4l2_standard *stddefs;
 312 
 313         if (pvrusb2_debug & PVR2_TRACE_STD) {
 314                 char buf[100];
 315                 bcnt = pvr2_std_id_to_str(buf,sizeof(buf),id);
 316                 pvr2_trace(
 317                         PVR2_TRACE_STD,"Mapping standards mask=0x%x (%.*s)",
 318                         (int)id,bcnt,buf);
 319         }
 320 
 321         *countptr = 0;
 322         std_cnt = 0;
 323         fmsk = 0;
 324         for (idmsk = 1, cmsk = id; cmsk; idmsk <<= 1) {
 325                 if (!(idmsk & cmsk)) continue;
 326                 cmsk &= ~idmsk;
 327                 if (match_std(idmsk)) {
 328                         std_cnt++;
 329                         continue;
 330                 }
 331                 fmsk |= idmsk;
 332         }
 333 
 334         for (idx2 = 0; idx2 < ARRAY_SIZE(std_mixes); idx2++) {
 335                 if ((id & std_mixes[idx2]) == std_mixes[idx2]) std_cnt++;
 336         }
 337 
 338         /* Don't complain about ATSC standard values */
 339         fmsk &= ~CSTD_ATSC;
 340 
 341         if (fmsk) {
 342                 char buf[100];
 343                 bcnt = pvr2_std_id_to_str(buf,sizeof(buf),fmsk);
 344                 pvr2_trace(
 345                         PVR2_TRACE_ERROR_LEGS,
 346                         "***WARNING*** Failed to classify the following standard(s): %.*s",
 347                         bcnt,buf);
 348         }
 349 
 350         pvr2_trace(PVR2_TRACE_STD,"Setting up %u unique standard(s)",
 351                    std_cnt);
 352         if (!std_cnt) return NULL; // paranoia
 353 
 354         stddefs = kcalloc(std_cnt, sizeof(struct v4l2_standard),
 355                           GFP_KERNEL);
 356         if (!stddefs)
 357                 return NULL;
 358 
 359         for (idx = 0; idx < std_cnt; idx++)
 360                 stddefs[idx].index = idx;
 361 
 362         idx = 0;
 363 
 364         /* Enumerate potential special cases */
 365         for (idx2 = 0; (idx2 < ARRAY_SIZE(std_mixes)) && (idx < std_cnt);
 366              idx2++) {
 367                 if (!(id & std_mixes[idx2])) continue;
 368                 if (pvr2_std_fill(stddefs+idx,std_mixes[idx2])) idx++;
 369         }
 370         /* Now enumerate individual pieces */
 371         for (idmsk = 1, cmsk = id; cmsk && (idx < std_cnt); idmsk <<= 1) {
 372                 if (!(idmsk & cmsk)) continue;
 373                 cmsk &= ~idmsk;
 374                 if (!pvr2_std_fill(stddefs+idx,idmsk)) continue;
 375                 idx++;
 376         }
 377 
 378         *countptr = std_cnt;
 379         return stddefs;
 380 }
 381 
 382 v4l2_std_id pvr2_std_get_usable(void)
 383 {
 384         return CSTD_ALL;
 385 }

/* [<][>][^][v][top][bottom][index][help] */