hc
2024-08-16 a24a44ff9ca902811b99aa9663d697cf452e08ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
#!/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