Difference between revisions of "PineCube as a webcam"
(Outsourced) |
(No difference)
|
Revision as of 10:29, 30 March 2023
The PineCube can be powered by the host and communicate as a peripheral. First, you'll need to a dual USB-A (male) cable to plug it into your computer. Note that the Micro-USB port can be used only for power because the data lines are not connected.
USB as an Ethernet gadget
Goal: To achieve fast (low latency) wired network connection via USB-A port of PineCube. PineCube will be shown as a network device when connected to a computer via USB-A port. You can set up the computer to be in the same network as PineCube and connect to PineCube via SSH and/or Stream Videos from it.
1. Additional patch to PineCube device tree disable ehci0 and ohci0, enabling usb_otg device instead and setting dr_mode to otg. If otg is not working for you, try setting dr_mode to peripheral. On Armbian there is no need for disabling ehci0 and ohci0. Device tree can be edited via armbian-config tool on Armbian OS. (armbian-config -> System -> DTC)
- sample DTC on Armbian:
-----
usb@1c19000 {
compatible = "allwinner,sun8i-h3-musb";
reg = <0x1c19000 0x400>;
clocks = <0x03 0x1d>;
resets = <0x03 0x11>;
interrupts = <0x00 0x47 0x04>;
interrupt-names = "mc";
phys = <0x0e 0x00>;
phy-names = "usb";
extcon = <0x0e 0x00>;
status = "okay";
dr_mode = "otg";
phandle = <0x2c>;
};
-----
2. Load necessary kernel modules. You can skip this step if you use Armbian OS because necessary modules are already loaded by default (Detailed instructions for sunxi and Ethernet gadget: https://linux-sunxi.org/USB_Gadget/Ethernet)
modprobe sunxi modprobe configfs modprobe libcomposite modprobe u_ether modprobe usb_f_rndis
3. Add sunxi and g_ether to /etc/modules to get them to load on startup
/etc/modules: sunxi g_ether
4. Configure the g_ether device to start with a stable MAC address
/etc/modprobe.d/g_ether.conf: options g_ether host_addr=f6:11:fd:ed:ec:6e
5. Set a static IP address for usb0 on startup with network manager
/etc/network/interfaces:
auto usb0
iface usb0 inet static
address 192.168.10.2
netmask 255.255.255.0
6. Boot the PineCube plugging it into a computer 7. Configure the USB Ethernet device on the computer to be in the same subnet as the PineCube
- Sample setting:
network setting: Manual address: 192.168.10.5 netmask: 255.255.255.0 gateway: 192.168.10.2
8. Done. You can use above methods to stream video through this USB Ethernet connection. Bandwidth and response time is much faster compared to usual network methods
USB as a Webcam (UVC) gadget (Work In Progress)
Goal: Make PineCube behave almost as same as like normal Webcam. When you connect PineCube to a computer it will be shown as a webcam device. No need for an additional set up you can use it straight after plugging the PineCube to a computer. USB-A port is for data transfer between PineCube and computer/phone. Micro-USB port is for power.
Action Plan (by Newton688):
-Attempt to load the uvc_gadget (usb_f_uvc) or g_webcam -Look at this project to see if it can bridge UVC gadget output with the v4l from the OV5650 camera sensor https://github.com/wlhe/uvc-gadget
Progress report so far (by Disctanger):
Configfs method is going to be used to control OTG port.
1. Additional patch to PineCube device tree disable ehci0 and ohci0, enabling usb_otg device instead and setting dr_mode to otg. If otg is not working for you, try setting dr_mode to peripheral. On Armbian there is no need for disabling ehci0 and ohci0. Device tree can be edited via armbian-config tool on Armbian OS. (armbian-config -> System -> DTC)
- sample DTC on Armbian:
-----
usb@1c19000 {
compatible = "allwinner,sun8i-h3-musb";
reg = <0x1c19000 0x400>;
clocks = <0x03 0x1d>;
resets = <0x03 0x11>;
interrupts = <0x00 0x47 0x04>;
interrupt-names = "mc";
phys = <0x0e 0x00>;
phy-names = "usb";
extcon = <0x0e 0x00>;
status = "okay";
dr_mode = "otg";
phandle = <0x2c>;
};
-----
2. Load necessary kernel modules.
modprobe sunxi modprobe configfs modprobe libcomposite
3. Set up camera so that it would capture images in YUYV format (Currently only supported format in UVC gadget). You can adjust resolutions but have to adjust Configfs set up step as well.
media-ctl --set-v4l2 '"ov5640 1-003c":0[fmt:YUYV8_2X8/640x480@1/30]'
4. Clone UVC gadget repo for raspberry pi to your PineCube
git clone https://github.com/peterbay/uvc-gadget.git cd uvc_gadget
5. Comment out 1182~1185 lines of `uvc-gadget.c` file:
// if (!uvc_shutdown_requested && ((uvc_dev.dqbuf_count + 1) >= uvc_dev.qbuf_count)) {
// return;
// }
6. Build the source code inside PineCube using make command. It takes only few seconds to build the code.
make gcc -W -Wall -g -c -o uvc-gadget.o uvc-gadget.c gcc -g -o uvc-gadget uvc-gadget.o
7. Set up configfs (multi-gadget):
You can have the following script as a bash script as well.
GADGET_PATH=/sys/kernel/config/usb_gadget/pinecube
mkdir $GADGET_PATH
echo 0x1d6b > $GADGET_PATH/idVendor
echo 0x0104 > $GADGET_PATH/idProduct
echo 0x0100 > $GADGET_PATH/bcdDevice
echo 0x0200 > $GADGET_PATH/bcdUSB
echo 0xEF > $GADGET_PATH/bDeviceClass
echo 0x02 > $GADGET_PATH/bDeviceSubClass
echo 0x01 > $GADGET_PATH/bDeviceProtocol
mkdir $GADGET_PATH/strings/0x409
echo 100000000d2386db > $GADGET_PATH/strings/0x409/serialnumber
echo "Pine64" > $GADGET_PATH/strings/0x409/manufacturer
echo "PineCube Webcam" > $GADGET_PATH/strings/0x409/product
mkdir $GADGET_PATH/configs/c.1
mkdir $GADGET_PATH/configs/c.1/strings/0x409
echo 500 > $GADGET_PATH/configs/c.1/MaxPower
echo "UVC" > $GADGET_PATH/configs/c.1/strings/0x409/configuration
mkdir $GADGET_PATH/functions/uvc.usb0
mkdir $GADGET_PATH/functions/acm.usb0
echo 512 > $GADGET_PATH/functions/uvc.usb0/streaming_maxpacket
# cat <<EOF $GADGET_PATH/functions/uvc.usb0/control/processing/default/bmControls
# 0
# 0
# EOF
mkdir -p $GADGET_PATH/functions/uvc.usb0/control/header/h
ln -s $GADGET_PATH/functions/uvc.usb0/control/header/h $GADGET_PATH/functions/uvc.usb0/control/class/fs/h
# ln -s $GADGET_PATH/functions/uvc.usb0/control/header/h $GADGET_PATH/functions/uvc.usb0/control/class/hs/h
# ln -s $GADGET_PATH/functions/uvc.usb0/control/header/h $GADGET_PATH/functions/uvc.usb0/control/class/ss/h
config_frame () {
FORMAT=$1
NAME=$2
WIDTH=$3
HEIGHT=$4
framedir=$GADGET_PATH/functions/uvc.usb0/streaming/$FORMAT/$NAME/${HEIGHT}p
mkdir -p $framedir
echo $WIDTH > $framedir/wWidth
echo $HEIGHT > $framedir/wHeight
echo 333333 > $framedir/dwDefaultFrameInterval
echo $(($WIDTH * $HEIGHT * 80)) > $framedir/dwMinBitRate
echo $(($WIDTH * $HEIGHT * 160)) > $framedir/dwMaxBitRate
echo $(($WIDTH * $HEIGHT * 2)) > $framedir/dwMaxVideoFrameBufferSize
cat <<EOF > $framedir/dwFrameInterval
333333
400000
666666
EOF
}
config_frame mjpeg m 640 360
config_frame mjpeg m 640 480
config_frame mjpeg m 800 600
config_frame mjpeg m 1024 768
config_frame mjpeg m 1280 720
config_frame mjpeg m 1280 960
config_frame mjpeg m 1440 1080
config_frame mjpeg m 1536 864
config_frame mjpeg m 1600 900
config_frame mjpeg m 1600 1200
config_frame mjpeg m 1920 1080
SMALL_WIDTH=480p
mkdir -p $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH
echo 640 > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/wWidth
echo 480 > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/wHeight
echo 333333 > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/dwDefaultFrameInterval
echo $((640 * 480 * 80)) > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/dwMinBitRate
echo $((640 * 480 * 160)) > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/dwMaxBitRate
echo $((640 * 480 * 2)) > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/dwMaxVideoFrameBufferSize
cat <<EOF > $GADGET_PATH/functions/uvc.usb0/streaming/uncompressed/u/$SMALL_WIDTH/dwFrameInterval
333333
400000
666666
EOF
mkdir $GADGET_PATH/functions/uvc.usb0/streaming/header/h
cd $GADGET_PATH/functions/uvc.usb0/streaming/header/h
# ln -s ../../mjpeg/m
ln -s ../../uncompressed/u
cd ../../class/fs
ln -s ../../header/h
cd ../../class/hs
ln -s ../../header/h
cd ../../../../..
ln -s $GADGET_PATH/functions/uvc.usb0 $GADGET_PATH/configs/c.1/uvc.usb0
ln -s $GADGET_PATH/functions/acm.usb0 $GADGET_PATH/configs/c.1/acm.usb0
udevadm settle -t 5 || :
ls /sys/class/udc > $GADGET_PATH/UDC
If above script goes without issues you should be able to see one more additional `/dev/video*` device.
8. run uvc-gadget
UVC Gadget software links camera of PineCube and UVC gadget (OTG port).
"-v" is for video input device - PineCube Camera, "-u" is for output video device UVC device or OTG port, -x shows FPS.
./uvc-gadget -u /dev/video1 -v /dev/video0 -x
9. Plug the PineCube to your laptop or pc and check if you can see PineCube Webcam.
Known issues:
- Low Frame rate(3FPS~5FPS). That is because:
- At the time of writing this section, `streaming_maxpacket` value cannot be set to max value (2048 bytes.) It can be set only to 512 bytes. If `streaming_maxpacket` is set to max (2048) value, UDC cannot be turned on with `Invalid Value` error.
- YUYV (uncompressed) file format is being used to stream the images. Uncompressed images take a lot of USB bandwidth compared to compressed. We can stream more frames, if MJPEG or even H254 (compressed images) would be used. I will be investigating further on how to stream more frames through USB port.

