Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pvrusb2-debugifc.c
Go to the documentation of this file.
1 /*
2  *
3  *
4  * Copyright (C) 2005 Mike Isely <[email protected]>
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 
27  const char *name;
28  unsigned long msk;
29 };
30 
31 
32 static 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 
49 static 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 
65 static 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 
93 static 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 
119 static 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 
130 int 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 
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 
195 static 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);
216  return 0;
217  } else if (debugifc_match_keyword(wptr,wlen,"bus")) {
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")) {
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")) {
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  }
300  "debugifc failed to recognize cmd: \"%.*s\"",wlen,wptr);
301  return -EINVAL;
302 }
303 
304 
305 int 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  */