2023-09-06 buildroot linux usb otg 口做RNDIS USB模拟以太网、ACM USB虚拟串口usb_rndis_en usb_acm_en .usb_config

一、usb otg 口做RNDIS USB模拟以太网

        1.1内核打开配置CONFIG_USB_CONFIGFS_RNDIS

        1.2 临时配置(重启后功能消失)

echo usb_rndis_en > /tmp/.usb_config
./etc/init.d/S50usbdevice restart

        1.3 永久配置

echo usb_rndis_en > /etc/init.d/.usb_config
./etc/init.d/S50usbdevice restart

        1.4 PC 网络连接会有RNDIS字样。

二、USB OTG 口做ACM USB虚拟串口,有文档说是用/usr/bin/usbdevice restart,但是我测试不行,用./etc/init.d/S50usbdevice restart才可以

        2.1 使能ACM后,可以在Device上看到/dev/ttyGS0设备

        2.2 临时配置(重启后功能消失)

echo usb_acm_en > /tmp/.usb_config
./etc/init.d/S50usbdevice restart

         2.3永久配置

echo usb_acm_en > /etc/init.d/.usb_config
./etc/init.d/S50usbdevice restart

        2.4 串口测试程序,收到什么就发送什么。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
 
int set_opt(int,int,int,char,int);
void main()
{
	int fd,nByte,flag=1;
	char *uart3 = "/dev/ttyGS0";
	char buffer[512];
	char *uart_out = "Please input,waiting....\r\n";
        char *uart_demo = "Linux uart demo\r\n";
	memset(buffer, 0, sizeof(buffer));
	//if((fd = open(uart3, O_RDWR|O_NOCTTY))<0)//默认为阻塞读方式
          if((fd = open(uart3, O_RDWR|O_NONBLOCK))<0)//非阻塞读方式
 
		printf("open %s is failed",uart3);
	else{
		set_opt(fd, 115200, 8, 'N', 1);
		write(fd,uart_demo, strlen(uart_demo));
                write(fd,uart_out, strlen(uart_out));
		while(1){
			while((nByte = read(fd, buffer, 512))>0){
				buffer[nByte+1] = '\0';			
				write(fd,buffer,strlen(buffer));
				memset(buffer, 0, strlen(buffer));
				nByte = 0;
			}
		}
	}
}
 
int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
	struct termios newtio,oldtio;
	if  ( tcgetattr( fd,&oldtio)  !=  0) { 
		perror("SetupSerial 1");
		return -1;
	}
	bzero( &newtio, sizeof( newtio ) );
	newtio.c_cflag  |=  CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;
 
	switch( nBits )
	{
		case 7:
			newtio.c_cflag |= CS7;
			break;
		case 8:
			newtio.c_cflag |= CS8;
			break;
	}
 
	switch( nEvent )
	{
	case 'O':
		newtio.c_cflag |= PARENB;
		newtio.c_cflag |= PARODD;
		newtio.c_iflag |= (INPCK | ISTRIP);
		break;
	case 'E': 
		newtio.c_iflag |= (INPCK | ISTRIP);
		newtio.c_cflag |= PARENB;
		newtio.c_cflag &= ~PARODD;
		break;
	case 'N':  
		newtio.c_cflag &= ~PARENB;
		break;
	}
 
	switch( nSpeed )
	{
		case 2400:
			cfsetispeed(&newtio, B2400);
			cfsetospeed(&newtio, B2400);
			break;
		case 4800:
			cfsetispeed(&newtio, B4800);
			cfsetospeed(&newtio, B4800);
			break;
		case 9600:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
		case 115200:
			cfsetispeed(&newtio, B115200);
			cfsetospeed(&newtio, B115200);
			break;
		case 460800:
			cfsetispeed(&newtio, B460800);
			cfsetospeed(&newtio, B460800);
			break;
		default:
			cfsetispeed(&newtio, B9600);
			cfsetospeed(&newtio, B9600);
			break;
	}
	if( nStop == 1 )
		newtio.c_cflag &=  ~CSTOPB;
	else if ( nStop == 2 )
		newtio.c_cflag |=  CSTOPB;
		newtio.c_cc[VTIME]  = 100;///* 设置超时10 seconds*/
		newtio.c_cc[VMIN] = 0;
		tcflush(fd,TCIFLUSH);
	if((tcsetattr(fd,TCSANOW,&newtio))!=0)
	{
		perror("com set error");
		return -1;
	}
	
	//	printf("set done!\n\r");
	return 0;
}
 

        2.5 测试效果,usb otg口可以当普通串口来用。

四、附上S50usbdevice 脚本代码

#!/bin/sh
#
# setup configfs for adbd, usb mass storage and MTP....
# For kernel v4.4 usb configfs
#
# Load default env variables from profiles
. /etc/profile

UMS_EN=off
ADB_EN=off
MTP_EN=off
NTB_EN=off
ACM_EN=off
UAC1_EN=off
UAC2_EN=off
UVC_EN=off
RNDIS_EN=off
HID_EN=off

USB_ATTRIBUTE=0x409
USB_GROUP=rockchip
USB_SKELETON=b.1

CONFIGFS_DIR=/sys/kernel/config
USB_CONFIGFS_DIR=${CONFIGFS_DIR}/usb_gadget/${USB_GROUP}
USB_STRINGS_DIR=${USB_CONFIGFS_DIR}/strings/${USB_ATTRIBUTE}
USB_FUNCTIONS_DIR=${USB_CONFIGFS_DIR}/functions
USB_CONFIGS_DIR=${USB_CONFIGFS_DIR}/configs/${USB_SKELETON}

# For VBUS_ALWAYS_ON usb otg is not support ums
# Since the block to ums is always occupated by USB due to no disconneted state
UMS_BLOCK=/userdata/ums_shared.img
UMS_BLOCK_SIZE=0	#unit M
UMS_BLOCK_TYPE=fat
UMS_BLOCK_AUTO_MOUNT=off
UMS_RO=0

UVC_DIR=${USB_FUNCTIONS_DIR}/uvc.gs6/
UVC_STREAMING_DIR=${UVC_DIR}/streaming/
UVC_CONTROL_DIR=${UVC_DIR}/control/
UVC_U_DIR=${UVC_STREAMING_DIR}/uncompressed/u/
UVC_M_DIR=${UVC_STREAMING_DIR}/mjpeg/m/
UVC_F_DIR=${UVC_STREAMING_DIR}/framebased/f/

test_write()
{
	test -e $2 && echo $1 > $2
}

function_init()
{
	mkdir ${USB_FUNCTIONS_DIR}/uac1.gs0
	test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/c_feature_unit
	test_write 1 ${USB_FUNCTIONS_DIR}/uac1.gs0/p_feature_unit
	mkdir ${USB_FUNCTIONS_DIR}/uac2.gs0
	test_write 1 ${USB_FUNCTIONS_DIR}/uac2.gs0/c_feature_unit
	test_write 1 ${USB_FUNCTIONS_DIR}/uac2.gs0/p_feature_unit
	mkdir ${USB_FUNCTIONS_DIR}/ffs.adb
	mkdir ${USB_FUNCTIONS_DIR}/ffs.ntb
	mkdir ${USB_FUNCTIONS_DIR}/mtp.gs0
	mkdir ${USB_FUNCTIONS_DIR}/rndis.gs0
	#write /config/usb_gadget/g1/functions/rndis.gs0/wceis 1
	mkdir ${USB_FUNCTIONS_DIR}/acm.gs6
	mkdir ${USB_FUNCTIONS_DIR}/mass_storage.0
	mkdir ${USB_FUNCTIONS_DIR}/uvc.gs6
	mkdir ${USB_FUNCTIONS_DIR}/hid.usb0
}

configfs_init()
{
	echo "Debug: configfs_init"
	mkdir /dev/usb-ffs

	mount -t configfs none ${CONFIGFS_DIR}
	mkdir ${USB_CONFIGFS_DIR} -m 0770
	echo 0x2207 > ${USB_CONFIGFS_DIR}/idVendor
	echo 0x0310 > ${USB_CONFIGFS_DIR}/bcdDevice
	echo 0x0200 > ${USB_CONFIGFS_DIR}/bcdUSB
	mkdir ${USB_STRINGS_DIR}   -m 0770
	SERIAL=`cat /proc/cpuinfo | grep Serial | awk '{print $3}'`
	if [ -z $SERIAL ];then
		SERIAL=0123456789ABCDEF
	fi
	echo $SERIAL > ${USB_STRINGS_DIR}/serialnumber
	echo "rockchip"  > ${USB_STRINGS_DIR}/manufacturer
	echo "rk3xxx"  > ${USB_STRINGS_DIR}/product

	function_init

	mkdir ${USB_CONFIGS_DIR}  -m 0770
	mkdir ${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE}  -m 0770

	echo 0x1 > ${USB_CONFIGFS_DIR}/os_desc/b_vendor_code
	echo "MSFT100" > ${USB_CONFIGFS_DIR}/os_desc/qw_sign
	echo 500 > ${USB_CONFIGS_DIR}/MaxPower
	ln -s ${USB_CONFIGS_DIR} ${USB_CONFIGFS_DIR}/os_desc/b.1
}

make_config_string()
{
	tmp=$CONFIG_STRING
	if [ -n "$CONFIG_STRING" ]; then
		CONFIG_STRING=${tmp}_${1}
	else
		CONFIG_STRING=$1
	fi
}

parse_parameter()
{
	# find name and var
	NAME=`echo $1 | awk -F "=" '{print $1}'`
	VAR=`echo $1 | awk -F "=" '{print $2}'`

	case "$NAME" in
		ums_block)
			UMS_BLOCK=${VAR}
			;;
		ums_block_size)
			if [ ! "$VAR" -gt 0 ] 2>/dev/null ;then
				echo "$VAR is not a number"
				exit 1
			fi
			UMS_BLOCK_SIZE=${VAR}
			;;
		ums_block_type)
			UMS_BLOCK_TYPE=${VAR}
			;;
		ums_block_auto_mount)
			UMS_BLOCK_AUTO_MOUNT=${VAR}
			;;
		ums_ro)
			if [ "$VAR" != "off" ]; then
				echo "Set UMS read-only"
				UMS_RO=1
			fi
				UMS_RO=0
			;;
	esac
}

parameter_init()
{
	while read line
	do
		case "$line" in
			usb_mtp_en)
				MTP_EN=on
				make_config_string mtp
				;;
			usb_adb_en)
				ADB_EN=on
				make_config_string adb
				;;
			usb_ums_en)
				UMS_EN=on
				make_config_string ums
				;;
			usb_ntb_en)
				NTB_EN=on
				make_config_string ntb
				;;
			usb_acm_en)
				ACM_EN=on
				make_config_string acm
				;;
			usb_uac1_en)
				UAC1_EN=on
				make_config_string uac1
				;;
			usb_uac2_en)
				UAC2_EN=on
				make_config_string uac2
				;;
			usb_uvc_en)
				UVC_EN=on
				make_config_string uvc
				;;
			usb_rndis_en)
				RNDIS_EN=on
				make_config_string rndis
				;;
			usb_hid_en)
				HID_EN=on
				make_config_string hid
				;;
			*)
				parse_parameter ${line}
				;;
		esac
	done < $USB_CONFIG_FILE

	case "$CONFIG_STRING" in
		ums)
			PID=0x0000
			;;
		mtp)
			PID=0x0001
			;;
		adb)
			PID=0x0006
			;;
		mtp_adb | adb_mtp)
			PID=0x0011
			;;
		ums_adb | adb_ums)
			PID=0x0018
			;;
		acm)
			PID=0x1005
			;;
		*)
			PID=0x0019
	esac
}

use_os_desc()
{
	if [ $MTP_EN = on ];then
		echo "MTP" > ${USB_FUNCTIONS_DIR}/mtp.gs0/os_desc/interface.MTP/compatible_id
		echo 1 > ${USB_CONFIGFS_DIR}/os_desc/use
	fi
}

pre_run_binary()
{
	if [ $ADB_EN = on ];then
		mkdir /dev/usb-ffs/adb -m 0770
		mount -o uid=2000,gid=2000 -t functionfs adb /dev/usb-ffs/adb
		start-stop-daemon --start --quiet --background --exec /usr/bin/adbd
	fi

	if [ $NTB_EN = on ];then
		mkdir /dev/usb-ffs/ntb -m 0770
		mount -o uid=2000,gid=2000 -t functionfs ntb /dev/usb-ffs/ntb
		# Not start app here
	fi

	# Add uvc app here with start-stop-daemon
}

configure_uvc_resolution_yuyv()
{
	W=$1
	H=$2
	DIR=${UVC_U_DIR}/${H}p/
	mkdir ${DIR}
	echo $W > ${DIR}/wWidth
	echo $H > ${DIR}/wHeight
	echo 333333 > ${DIR}/dwDefaultFrameInterval
	echo $((W*H*20)) > ${DIR}/dwMinBitRate
	echo $((W*H*20)) > ${DIR}/dwMaxBitRate
	echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize
	echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval
}

configure_uvc_resolution_mjpeg()
{
	W=$1
	H=$2
	DIR=${UVC_M_DIR}/${H}p/
	mkdir ${DIR}
	echo $W > ${DIR}/wWidth
	echo $H > ${DIR}/wHeight
	echo 333333 > ${DIR}/dwDefaultFrameInterval
	echo $((W*H*20)) > ${DIR}/dwMinBitRate
	echo $((W*H*20)) > ${DIR}/dwMaxBitRate
	echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize
	echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval
}

configure_uvc_resolution_h264()
{
	W=$1
	H=$2
	DIR=${UVC_F_DIR}/${H}p/
	mkdir ${DIR}
	echo $W > ${DIR}/wWidth
	echo $H > ${DIR}/wHeight
	echo 333333 > ${DIR}/dwDefaultFrameInterval
	echo $((W*H*10)) > ${DIR}/dwMinBitRate
	echo $((W*H*10)) > ${DIR}/dwMaxBitRate
	#echo $((W*H*2)) > ${DIR}/dwMaxVideoFrameBufferSize
	echo -e "333333\n666666\n1000000\n2000000" > ${DIR}/dwFrameInterval
}

syslink_function()
{
	ln -s ${USB_FUNCTIONS_DIR}/$1 ${USB_CONFIGS_DIR}/f${USB_FUNCTIONS_CNT}
	let USB_FUNCTIONS_CNT=USB_FUNCTIONS_CNT+1
}

bind_functions()
{
	USB_FUNCTIONS_CNT=1

	test $UAC1_EN = on && syslink_function uac1.gs0
	test $UAC2_EN = on && syslink_function uac2.gs0

	if [ $UVC_EN = on ];then
		#echo 3072 > ${UVC_DIR}/streaming_maxpacket
		#echo 1 > ${UVC_DIR}/streaming_bulk

		mkdir ${UVC_CONTROL_DIR}/header/h
		ln -s ${UVC_CONTROL_DIR}/header/h ${UVC_CONTROL_DIR}/class/fs/h
		ln -s ${UVC_CONTROL_DIR}/header/h ${UVC_CONTROL_DIR}/class/ss/h

		##YUYV support config
		mkdir ${UVC_U_DIR}
		configure_uvc_resolution_yuyv 640 480
		configure_uvc_resolution_yuyv 1280 720

		##mjpeg support config
		mkdir ${UVC_M_DIR}
		configure_uvc_resolution_mjpeg 640 480
		configure_uvc_resolution_mjpeg 1280 720
		configure_uvc_resolution_mjpeg 1920 1080
		configure_uvc_resolution_mjpeg 2560 1440
		configure_uvc_resolution_mjpeg 2592 1944

		## h.264 support config
		mkdir ${UVC_F_DIR}
		configure_uvc_resolution_h264 640 480
		configure_uvc_resolution_h264 1280 720
		configure_uvc_resolution_h264 1920 1080

		mkdir ${UVC_STREAMING_DIR}/header/h
		ln -s ${UVC_U_DIR} ${UVC_STREAMING_DIR}/header/h/u
		ln -s ${UVC_M_DIR} ${UVC_STREAMING_DIR}/header/h/m
		ln -s ${UVC_F_DIR} ${UVC_STREAMING_DIR}/header/h/f
		ln -s ${UVC_STREAMING_DIR}/header/h ${UVC_STREAMING_DIR}/class/fs/h
		ln -s ${UVC_STREAMING_DIR}/header/h ${UVC_STREAMING_DIR}/class/hs/h
		ln -s ${UVC_STREAMING_DIR}/header/h ${UVC_STREAMING_DIR}/class/ss/h

		syslink_function uvc.gs6
	fi

	test $MTP_EN = on && syslink_function mtp.gs0
	test $NTB_EN = on && syslink_function ffs.ntb
	test $ADB_EN = on && syslink_function ffs.adb
	test $ACM_EN = on && syslink_function acm.gs6
	test $RNDIS_EN = on && syslink_function rndis.gs0

	if [ $HID_EN = on ]; then
		echo 1 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/protocol
		echo 1 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/subclass
		echo 8 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_length
		echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > /sys/kernel/config/usb_gadget/rockchip/functions/hid.usb0/report_desc
		syslink_function hid.usb0
	fi

	if [ $UMS_EN = on ];then
		echo ${UMS_RO} > ${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/ro
		if [ "$UMS_BLOCK_SIZE" != "0" -a ! -e ${UMS_BLOCK} ]; then
			dd if=/dev/zero of=${UMS_BLOCK} bs=1M count=${UMS_BLOCK_SIZE}
			mkfs.${UMS_BLOCK_TYPE} ${UMS_BLOCK}
			test $? && echo "Warning: failed to mkfs.${UMS_BLOCK_TYPE} ${UMS_BLOCK}"
		fi
		mkdir /mnt/ums -p
		if [ $UMS_BLOCK_AUTO_MOUNT = on ];then
			mount ${UMS_BLOCK} /mnt/ums
		else
			echo ${UMS_BLOCK} > ${USB_FUNCTIONS_DIR}/mass_storage.0/lun.0/file
		fi
		syslink_function mass_storage.0
	fi

	echo ${CONFIG_STRING} > ${USB_CONFIGS_DIR}/strings/${USB_ATTRIBUTE}/configuration
}

run_binary()
{
	if [ $MTP_EN = on ];then
		start-stop-daemon --start --quiet --background --exec /usr/bin/mtp-server
	fi
}

program_kill()
{
	P_PID=`ps | grep $1 | grep -v grep | awk '{print $1}'`
	test -z ${P_PID} || kill -9 ${P_PID}
}

usb_device_stop()
{
	echo "none" > ${USB_CONFIGFS_DIR}/UDC
	program_kill adbd
	program_kill mtp-server
	ls ${USB_CONFIGS_DIR} | grep f[0-9] | xargs -I {} rm ${USB_CONFIGS_DIR}/{}
}

case "$1" in
start)
	DIR=$(cd `dirname $0`; pwd)
	if [ ! -e "$DIR/.usb_config" ]; then
		echo "$0: Cannot find .usb_config"
		exit 0
	fi

	if [ -e /tmp/.usb_config ]; then
		USB_CONFIG_FILE=/tmp/.usb_config
	else
		USB_CONFIG_FILE=$DIR/.usb_config
		cp $DIR/.usb_config /tmp/.usb_config
	fi

	parameter_init
	if [ -z $CONFIG_STRING ]; then
		echo "$0: no function be selected"
		exit 0
	fi
	test -d ${USB_CONFIGFS_DIR} || configfs_init
	use_os_desc
	echo $PID > ${USB_CONFIGFS_DIR}/idProduct
	bind_functions
	pre_run_binary
	sleep 1
	UDC=`ls /sys/class/udc/| awk '{print $1}'`
	echo $UDC > ${USB_CONFIGFS_DIR}/UDC
	run_binary
	;;
stop)
	usb_device_stop
	;;
restart|reload)
	# Do restart usb by udev
	echo "USB_FORCE_CHANGED" >> /tmp/.usb_config
	usb_device_stop
	sleep 1
	$0 start
	# Don't forget to clear "USB_FORCE_CHANGED"
	sed -i "/USB_FORCE_CHANGED/d" /tmp/.usb_config
	;;
*)
	echo "Usage: $0 {start|stop|restart}"
	exit 1
esac

exit 0

五、有价值的参考文章

23. USB — 快速使用手册—基于LubanCat-RK356x系列板卡 文档

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值