linux/drivers/media/usb/pvrusb2/pvrusb2-debugifc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *
   4 *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
   5 */
   6
   7#include <linux/string.h>
   8#include "pvrusb2-debugifc.h"
   9#include "pvrusb2-hdw.h"
  10#include "pvrusb2-debug.h"
  11
  12struct debugifc_mask_item {
  13        const char *name;
  14        unsigned long msk;
  15};
  16
  17
  18static unsigned int debugifc_count_whitespace(const char *buf,
  19                                              unsigned int count)
  20{
  21        unsigned int scnt;
  22        char ch;
  23
  24        for (scnt = 0; scnt < count; scnt++) {
  25                ch = buf[scnt];
  26                if (ch == ' ') continue;
  27                if (ch == '\t') continue;
  28                if (ch == '\n') continue;
  29                break;
  30        }
  31        return scnt;
  32}
  33
  34
  35static unsigned int debugifc_count_nonwhitespace(const char *buf,
  36                                                 unsigned int count)
  37{
  38        unsigned int scnt;
  39        char ch;
  40
  41        for (scnt = 0; scnt < count; scnt++) {
  42                ch = buf[scnt];
  43                if (ch == ' ') break;
  44                if (ch == '\t') break;
  45                if (ch == '\n') break;
  46        }
  47        return scnt;
  48}
  49
  50
  51static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
  52                                          const char **wstrPtr,
  53                                          unsigned int *wlenPtr)
  54{
  55        const char *wptr;
  56        unsigned int consume_cnt = 0;
  57        unsigned int wlen;
  58        unsigned int scnt;
  59
  60        wptr = NULL;
  61        wlen = 0;
  62        scnt = debugifc_count_whitespace(buf,count);
  63        consume_cnt += scnt; count -= scnt; buf += scnt;
  64        if (!count) goto done;
  65
  66        scnt = debugifc_count_nonwhitespace(buf,count);
  67        if (!scnt) goto done;
  68        wptr = buf;
  69        wlen = scnt;
  70        consume_cnt += scnt; count -= scnt; buf += scnt;
  71
  72 done:
  73        *wstrPtr = wptr;
  74        *wlenPtr = wlen;
  75        return consume_cnt;
  76}
  77
  78
  79static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
  80                                          u32 *num_ptr)
  81{
  82        u32 result = 0;
  83        int radix = 10;
  84        if ((count >= 2) && (buf[0] == '0') &&
  85            ((buf[1] == 'x') || (buf[1] == 'X'))) {
  86                radix = 16;
  87                count -= 2;
  88                buf += 2;
  89        } else if ((count >= 1) && (buf[0] == '0')) {
  90                radix = 8;
  91        }
  92
  93        while (count--) {
  94                int val = hex_to_bin(*buf++);
  95                if (val < 0 || val >= radix)
  96                        return -EINVAL;
  97                result *= radix;
  98                result += val;
  99        }
 100        *num_ptr = result;
 101        return 0;
 102}
 103
 104
 105static int debugifc_match_keyword(const char *buf,unsigned int count,
 106                                  const char *keyword)
 107{
 108        unsigned int kl;
 109        if (!keyword) return 0;
 110        kl = strlen(keyword);
 111        if (kl != count) return 0;
 112        return !memcmp(buf,keyword,kl);
 113}
 114
 115
 116int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
 117{
 118        int bcnt = 0;
 119        int ccnt;
 120        ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n",
 121                         pvr2_hdw_get_desc(hdw));
 122        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 123        ccnt = scnprintf(buf,acnt,"Driver state info:\n");
 124        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 125        ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
 126        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 127
 128        return bcnt;
 129}
 130
 131
 132int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
 133                               char *buf,unsigned int acnt)
 134{
 135        int bcnt = 0;
 136        int ccnt;
 137        int ret;
 138        u32 gpio_dir,gpio_in,gpio_out;
 139        struct pvr2_stream_stats stats;
 140        struct pvr2_stream *sp;
 141
 142        ret = pvr2_hdw_is_hsm(hdw);
 143        ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
 144                         (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
 145        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 146
 147        gpio_dir = 0; gpio_in = 0; gpio_out = 0;
 148        pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
 149        pvr2_hdw_gpio_get_out(hdw,&gpio_out);
 150        pvr2_hdw_gpio_get_in(hdw,&gpio_in);
 151        ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
 152                         gpio_dir,gpio_in,gpio_out);
 153        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 154
 155        ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
 156                         pvr2_hdw_get_streaming(hdw) ? "on" : "off");
 157        bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 158
 159
 160        sp = pvr2_hdw_get_video_stream(hdw);
 161        if (sp) {
 162                pvr2_stream_get_stats(sp, &stats, 0);
 163                ccnt = scnprintf(
 164                        buf,acnt,
 165                        "Bytes streamed=%u URBs: queued=%u idle=%u ready=%u processed=%u failed=%u\n",
 166                        stats.bytes_processed,
 167                        stats.buffers_in_queue,
 168                        stats.buffers_in_idle,
 169                        stats.buffers_in_ready,
 170                        stats.buffers_processed,
 171                        stats.buffers_failed);
 172                bcnt += ccnt; acnt -= ccnt; buf += ccnt;
 173        }
 174
 175        return bcnt;
 176}
 177
 178
 179static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
 180                                unsigned int count)
 181{
 182        const char *wptr;
 183        unsigned int wlen;
 184        unsigned int scnt;
 185
 186        scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 187        if (!scnt) return 0;
 188        count -= scnt; buf += scnt;
 189        if (!wptr) return 0;
 190
 191        pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
 192        if (debugifc_match_keyword(wptr,wlen,"reset")) {
 193                scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 194                if (!scnt) return -EINVAL;
 195                count -= scnt; buf += scnt;
 196                if (!wptr) return -EINVAL;
 197                if (debugifc_match_keyword(wptr,wlen,"cpu")) {
 198                        pvr2_hdw_cpureset_assert(hdw,!0);
 199                        pvr2_hdw_cpureset_assert(hdw,0);
 200                        return 0;
 201                } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
 202                        pvr2_hdw_device_reset(hdw);
 203                } else if (debugifc_match_keyword(wptr,wlen,"soft")) {
 204                        return pvr2_hdw_cmd_powerup(hdw);
 205                } else if (debugifc_match_keyword(wptr,wlen,"deep")) {
 206                        return pvr2_hdw_cmd_deep_reset(hdw);
 207                } else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
 208                        return pvr2_upload_firmware2(hdw);
 209                } else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
 210                        return pvr2_hdw_cmd_decoder_reset(hdw);
 211                } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
 212                        return pvr2_hdw_untrip(hdw);
 213                } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
 214                        pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
 215                                              NULL, !0);
 216                        return 0;
 217                }
 218                return -EINVAL;
 219        } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
 220                scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 221                if (!scnt) return -EINVAL;
 222                count -= scnt; buf += scnt;
 223                if (!wptr) return -EINVAL;
 224                if (debugifc_match_keyword(wptr,wlen,"fetch")) {
 225                        scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 226                        if (scnt && wptr) {
 227                                count -= scnt; buf += scnt;
 228                                if (debugifc_match_keyword(wptr, wlen,
 229                                                           "prom")) {
 230                                        pvr2_hdw_cpufw_set_enabled(hdw, 2, !0);
 231                                } else if (debugifc_match_keyword(wptr, wlen,
 232                                                                  "ram8k")) {
 233                                        pvr2_hdw_cpufw_set_enabled(hdw, 0, !0);
 234                                } else if (debugifc_match_keyword(wptr, wlen,
 235                                                                  "ram16k")) {
 236                                        pvr2_hdw_cpufw_set_enabled(hdw, 1, !0);
 237                                } else {
 238                                        return -EINVAL;
 239                                }
 240                        }
 241                        pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
 242                        return 0;
 243                } else if (debugifc_match_keyword(wptr,wlen,"done")) {
 244                        pvr2_hdw_cpufw_set_enabled(hdw,0,0);
 245                        return 0;
 246                } else {
 247                        return -EINVAL;
 248                }
 249        } else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
 250                int dir_fl = 0;
 251                int ret;
 252                u32 msk,val;
 253                scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 254                if (!scnt) return -EINVAL;
 255                count -= scnt; buf += scnt;
 256                if (!wptr) return -EINVAL;
 257                if (debugifc_match_keyword(wptr,wlen,"dir")) {
 258                        dir_fl = !0;
 259                } else if (!debugifc_match_keyword(wptr,wlen,"out")) {
 260                        return -EINVAL;
 261                }
 262                scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 263                if (!scnt) return -EINVAL;
 264                count -= scnt; buf += scnt;
 265                if (!wptr) return -EINVAL;
 266                ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
 267                if (ret) return ret;
 268                scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
 269                if (wptr) {
 270                        ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
 271                        if (ret) return ret;
 272                } else {
 273                        val = msk;
 274                        msk = 0xffffffff;
 275                }
 276                if (dir_fl) {
 277                        ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
 278                } else {
 279                        ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
 280                }
 281                return ret;
 282        }
 283        pvr2_trace(PVR2_TRACE_DEBUGIFC,
 284                   "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
 285        return -EINVAL;
 286}
 287
 288
 289int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
 290                        unsigned int count)
 291{
 292        unsigned int bcnt = 0;
 293        int ret;
 294
 295        while (count) {
 296                for (bcnt = 0; bcnt < count; bcnt++) {
 297                        if (buf[bcnt] == '\n') break;
 298                }
 299
 300                ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
 301                if (ret < 0) return ret;
 302                if (bcnt < count) bcnt++;
 303                buf += bcnt;
 304                count -= bcnt;
 305        }
 306
 307        return 0;
 308}
 309