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