Merge tag 'for-linus-5.6-ofs1' of git://git.kernel.org/pub/scm/linux/kernel/git/hubca...
[linux-2.6-microblaze.git] / drivers / media / usb / pvrusb2 / pvrusb2-debugifc.c
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
12 struct debugifc_mask_item {
13         const char *name;
14         unsigned long msk;
15 };
16
17
18 static 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
35 static 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
51 static 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
79 static 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
105 static 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
116 int 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
132 int 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
179 static 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
289 int 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 }