brintos

brintos / linux-shallow public Read only

0
0
Text · 7.5 KiB · 81d7112 Raw
304 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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}304