0001
0002
0003
0004
0005
0006
0007 #include <linux/string.h>
0008 #include "pvrusb2-debugifc.h"
0009 #include "pvrusb2-hdw.h"
0010 #include "pvrusb2-debug.h"
0011
0012 struct debugifc_mask_item {
0013 const char *name;
0014 unsigned long msk;
0015 };
0016
0017
0018 static unsigned int debugifc_count_whitespace(const char *buf,
0019 unsigned int count)
0020 {
0021 unsigned int scnt;
0022 char ch;
0023
0024 for (scnt = 0; scnt < count; scnt++) {
0025 ch = buf[scnt];
0026 if (ch == ' ') continue;
0027 if (ch == '\t') continue;
0028 if (ch == '\n') continue;
0029 break;
0030 }
0031 return scnt;
0032 }
0033
0034
0035 static unsigned int debugifc_count_nonwhitespace(const char *buf,
0036 unsigned int count)
0037 {
0038 unsigned int scnt;
0039 char ch;
0040
0041 for (scnt = 0; scnt < count; scnt++) {
0042 ch = buf[scnt];
0043 if (ch == ' ') break;
0044 if (ch == '\t') break;
0045 if (ch == '\n') break;
0046 }
0047 return scnt;
0048 }
0049
0050
0051 static unsigned int debugifc_isolate_word(const char *buf,unsigned int count,
0052 const char **wstrPtr,
0053 unsigned int *wlenPtr)
0054 {
0055 const char *wptr;
0056 unsigned int consume_cnt = 0;
0057 unsigned int wlen;
0058 unsigned int scnt;
0059
0060 wptr = NULL;
0061 wlen = 0;
0062 scnt = debugifc_count_whitespace(buf,count);
0063 consume_cnt += scnt; count -= scnt; buf += scnt;
0064 if (!count) goto done;
0065
0066 scnt = debugifc_count_nonwhitespace(buf,count);
0067 if (!scnt) goto done;
0068 wptr = buf;
0069 wlen = scnt;
0070 consume_cnt += scnt; count -= scnt; buf += scnt;
0071
0072 done:
0073 *wstrPtr = wptr;
0074 *wlenPtr = wlen;
0075 return consume_cnt;
0076 }
0077
0078
0079 static int debugifc_parse_unsigned_number(const char *buf,unsigned int count,
0080 u32 *num_ptr)
0081 {
0082 u32 result = 0;
0083 int radix = 10;
0084 if ((count >= 2) && (buf[0] == '0') &&
0085 ((buf[1] == 'x') || (buf[1] == 'X'))) {
0086 radix = 16;
0087 count -= 2;
0088 buf += 2;
0089 } else if ((count >= 1) && (buf[0] == '0')) {
0090 radix = 8;
0091 }
0092
0093 while (count--) {
0094 int val = hex_to_bin(*buf++);
0095 if (val < 0 || val >= radix)
0096 return -EINVAL;
0097 result *= radix;
0098 result += val;
0099 }
0100 *num_ptr = result;
0101 return 0;
0102 }
0103
0104
0105 static int debugifc_match_keyword(const char *buf,unsigned int count,
0106 const char *keyword)
0107 {
0108 unsigned int kl;
0109 if (!keyword) return 0;
0110 kl = strlen(keyword);
0111 if (kl != count) return 0;
0112 return !memcmp(buf,keyword,kl);
0113 }
0114
0115
0116 int pvr2_debugifc_print_info(struct pvr2_hdw *hdw,char *buf,unsigned int acnt)
0117 {
0118 int bcnt = 0;
0119 int ccnt;
0120 ccnt = scnprintf(buf, acnt, "Driver hardware description: %s\n",
0121 pvr2_hdw_get_desc(hdw));
0122 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0123 ccnt = scnprintf(buf,acnt,"Driver state info:\n");
0124 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0125 ccnt = pvr2_hdw_state_report(hdw,buf,acnt);
0126 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0127
0128 return bcnt;
0129 }
0130
0131
0132 int pvr2_debugifc_print_status(struct pvr2_hdw *hdw,
0133 char *buf,unsigned int acnt)
0134 {
0135 int bcnt = 0;
0136 int ccnt;
0137 int ret;
0138 u32 gpio_dir,gpio_in,gpio_out;
0139 struct pvr2_stream_stats stats;
0140 struct pvr2_stream *sp;
0141
0142 ret = pvr2_hdw_is_hsm(hdw);
0143 ccnt = scnprintf(buf,acnt,"USB link speed: %s\n",
0144 (ret < 0 ? "FAIL" : (ret ? "high" : "full")));
0145 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0146
0147 gpio_dir = 0; gpio_in = 0; gpio_out = 0;
0148 pvr2_hdw_gpio_get_dir(hdw,&gpio_dir);
0149 pvr2_hdw_gpio_get_out(hdw,&gpio_out);
0150 pvr2_hdw_gpio_get_in(hdw,&gpio_in);
0151 ccnt = scnprintf(buf,acnt,"GPIO state: dir=0x%x in=0x%x out=0x%x\n",
0152 gpio_dir,gpio_in,gpio_out);
0153 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0154
0155 ccnt = scnprintf(buf,acnt,"Streaming is %s\n",
0156 pvr2_hdw_get_streaming(hdw) ? "on" : "off");
0157 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0158
0159
0160 sp = pvr2_hdw_get_video_stream(hdw);
0161 if (sp) {
0162 pvr2_stream_get_stats(sp, &stats, 0);
0163 ccnt = scnprintf(
0164 buf,acnt,
0165 "Bytes streamed=%u URBs: queued=%u idle=%u ready=%u processed=%u failed=%u\n",
0166 stats.bytes_processed,
0167 stats.buffers_in_queue,
0168 stats.buffers_in_idle,
0169 stats.buffers_in_ready,
0170 stats.buffers_processed,
0171 stats.buffers_failed);
0172 bcnt += ccnt; acnt -= ccnt; buf += ccnt;
0173 }
0174
0175 return bcnt;
0176 }
0177
0178
0179 static int pvr2_debugifc_do1cmd(struct pvr2_hdw *hdw,const char *buf,
0180 unsigned int count)
0181 {
0182 const char *wptr;
0183 unsigned int wlen;
0184 unsigned int scnt;
0185
0186 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0187 if (!scnt) return 0;
0188 count -= scnt; buf += scnt;
0189 if (!wptr) return 0;
0190
0191 pvr2_trace(PVR2_TRACE_DEBUGIFC,"debugifc cmd: \"%.*s\"",wlen,wptr);
0192 if (debugifc_match_keyword(wptr,wlen,"reset")) {
0193 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0194 if (!scnt) return -EINVAL;
0195 count -= scnt; buf += scnt;
0196 if (!wptr) return -EINVAL;
0197 if (debugifc_match_keyword(wptr,wlen,"cpu")) {
0198 pvr2_hdw_cpureset_assert(hdw,!0);
0199 pvr2_hdw_cpureset_assert(hdw,0);
0200 return 0;
0201 } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
0202 pvr2_hdw_device_reset(hdw);
0203 } else if (debugifc_match_keyword(wptr,wlen,"soft")) {
0204 return pvr2_hdw_cmd_powerup(hdw);
0205 } else if (debugifc_match_keyword(wptr,wlen,"deep")) {
0206 return pvr2_hdw_cmd_deep_reset(hdw);
0207 } else if (debugifc_match_keyword(wptr,wlen,"firmware")) {
0208 return pvr2_upload_firmware2(hdw);
0209 } else if (debugifc_match_keyword(wptr,wlen,"decoder")) {
0210 return pvr2_hdw_cmd_decoder_reset(hdw);
0211 } else if (debugifc_match_keyword(wptr,wlen,"worker")) {
0212 return pvr2_hdw_untrip(hdw);
0213 } else if (debugifc_match_keyword(wptr,wlen,"usbstats")) {
0214 pvr2_stream_get_stats(pvr2_hdw_get_video_stream(hdw),
0215 NULL, !0);
0216 return 0;
0217 }
0218 return -EINVAL;
0219 } else if (debugifc_match_keyword(wptr,wlen,"cpufw")) {
0220 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0221 if (!scnt) return -EINVAL;
0222 count -= scnt; buf += scnt;
0223 if (!wptr) return -EINVAL;
0224 if (debugifc_match_keyword(wptr,wlen,"fetch")) {
0225 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0226 if (scnt && wptr) {
0227 count -= scnt; buf += scnt;
0228 if (debugifc_match_keyword(wptr, wlen,
0229 "prom")) {
0230 pvr2_hdw_cpufw_set_enabled(hdw, 2, !0);
0231 } else if (debugifc_match_keyword(wptr, wlen,
0232 "ram8k")) {
0233 pvr2_hdw_cpufw_set_enabled(hdw, 0, !0);
0234 } else if (debugifc_match_keyword(wptr, wlen,
0235 "ram16k")) {
0236 pvr2_hdw_cpufw_set_enabled(hdw, 1, !0);
0237 } else {
0238 return -EINVAL;
0239 }
0240 }
0241 pvr2_hdw_cpufw_set_enabled(hdw,0,!0);
0242 return 0;
0243 } else if (debugifc_match_keyword(wptr,wlen,"done")) {
0244 pvr2_hdw_cpufw_set_enabled(hdw,0,0);
0245 return 0;
0246 } else {
0247 return -EINVAL;
0248 }
0249 } else if (debugifc_match_keyword(wptr,wlen,"gpio")) {
0250 int dir_fl = 0;
0251 int ret;
0252 u32 msk,val;
0253 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0254 if (!scnt) return -EINVAL;
0255 count -= scnt; buf += scnt;
0256 if (!wptr) return -EINVAL;
0257 if (debugifc_match_keyword(wptr,wlen,"dir")) {
0258 dir_fl = !0;
0259 } else if (!debugifc_match_keyword(wptr,wlen,"out")) {
0260 return -EINVAL;
0261 }
0262 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0263 if (!scnt) return -EINVAL;
0264 count -= scnt; buf += scnt;
0265 if (!wptr) return -EINVAL;
0266 ret = debugifc_parse_unsigned_number(wptr,wlen,&msk);
0267 if (ret) return ret;
0268 scnt = debugifc_isolate_word(buf,count,&wptr,&wlen);
0269 if (wptr) {
0270 ret = debugifc_parse_unsigned_number(wptr,wlen,&val);
0271 if (ret) return ret;
0272 } else {
0273 val = msk;
0274 msk = 0xffffffff;
0275 }
0276 if (dir_fl) {
0277 ret = pvr2_hdw_gpio_chg_dir(hdw,msk,val);
0278 } else {
0279 ret = pvr2_hdw_gpio_chg_out(hdw,msk,val);
0280 }
0281 return ret;
0282 }
0283 pvr2_trace(PVR2_TRACE_DEBUGIFC,
0284 "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
0285 return -EINVAL;
0286 }
0287
0288
0289 int pvr2_debugifc_docmd(struct pvr2_hdw *hdw,const char *buf,
0290 unsigned int count)
0291 {
0292 unsigned int bcnt = 0;
0293 int ret;
0294
0295 while (count) {
0296 for (bcnt = 0; bcnt < count; bcnt++) {
0297 if (buf[bcnt] == '\n') break;
0298 }
0299
0300 ret = pvr2_debugifc_do1cmd(hdw,buf,bcnt);
0301 if (ret < 0) return ret;
0302 if (bcnt < count) bcnt++;
0303 buf += bcnt;
0304 count -= bcnt;
0305 }
0306
0307 return 0;
0308 }