Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
v6.9.4
  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
 12struct debugifc_mask_item {
 13	const char *name;
 14	unsigned long msk;
 15};
 16
 17
 18static 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
 35static 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
 51static 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
 79static 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
105static 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
116int 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
132int 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
179static 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
289int 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}
v5.14.15
  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
 12struct debugifc_mask_item {
 13	const char *name;
 14	unsigned long msk;
 15};
 16
 17
 18static 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
 35static 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
 51static 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
 79static 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
105static 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
116int 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
132int 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
179static 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
289int 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}