File Index
Files and directories
Sign in
FILE

pvrusb2-debugifc.c

File preview with syntax highlighting.

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