VoCore2: USB Device Develop

Such a simple code but get mistake…

My source code is as simple as usual

...in fbusb_probe for a new usb device...

		u8 buf[6] = {0x00, 0x2c, 0x00, 0xb8, 0x0b, 0x00};
		usb_control_msg(par->udev, usb_sndctrlpipe(par->udev, 0), 0xb0,
			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
			0, 0, buf, 6, 100);
...

every parameter should be normal, but once the code runs at this position, it crashed…

[   71.998261] ------------[ cut here ]------------
[   72.002980] WARNING: CPU: 0 PID: 347 at drivers/usb/core/hcd.c:1598 usb_hcd_map_urb_for_dma+0x3f4/0x524
[   72.012519] transfer buffer is on stack
[   72.016416] Modules linked in: pppoe ppp_async pppox ppp_generic nf_conntrack_ipv6 lzo iptable_nat ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_FLOWOFFLOAD slhc nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_conntrack_ipv4 nf_nat_ipv4 nf_nat nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack_rtcache nf_conntrack lzo_decompress lzo_compress iptable_mangle iptable_filter ip_tables crc_ccitt mt7628 i2c_mt7621 snd_soc_core ralink_gdma virt_dma i2c_dev ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables snd_compress snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_rawmidi snd_seq_device snd_hwdep snd
[   72.088165]  input_core soundcore vfat fat nls_utf8 nls_iso8859_1 nls_cp437 regmap_spi regmap_i2c i2c_core crypto_acompress mmc_block usb_storage mtk_sd mmc_core leds_gpio ohci_platform ohci_hcd ehci_platform sd_mod scsi_mod ehci_hcd gpio_button_hotplug
[   72.111025] CPU: 0 PID: 347 Comm: kworker/0:3 Not tainted 4.14.50 #0
[   72.117496] Workqueue: usb_hub_wq hub_event
[   72.121735] Stack : 86846000 804635c8 86846610 8004e674 87e2b454 80447aa7 803f1944 0000015b
[   72.130235]         803f18b0 87f5187c 86846000 8004f350 86846610 87fd3915 87f51858 24c668a7
[   72.138735]         00000000 00000000 00000000 000000c2 00000000 65756575 7375203a 75685f62
[   72.147234]         00000001 00000000 00000040 63686520 00000000 00000000 802279e8 80412a8c
[   72.155732]         00000009 0000063e 86846000 804635c8 00000002 801db240 00000000 804a0000
[   72.164288]         ...
[   72.166788] Call Trace:
[   72.169290] [<8000e424>] show_stack+0x74/0x104
[   72.173818] [<800245a0>] __warn+0x110/0x118
[   72.178088] [<800245d8>] warn_slowpath_fmt+0x30/0x3c
[   72.183145] [<802279e8>] usb_hcd_map_urb_for_dma+0x3f4/0x524
[   72.188899] [<80228d30>] usb_hcd_submit_urb+0x79c/0x7d0
[   72.194203] [<8022a2c0>] usb_start_wait_urb+0x5c/0xec
[   72.199338] [<8022a400>] usb_control_msg+0xb0/0x114
[   72.204296] [<801c4cfc>] fbusb_probe+0x260/0x2bc
[   72.208995] [<8022dd48>] usb_probe_interface+0x1cc/0x1f4
[   72.214399] [<801e9824>] driver_probe_device+0x1fc/0x2c4
[   72.219799] [<801e7c84>] bus_for_each_drv+0x9c/0xac
[   72.224749] [<801e95d4>] __device_attach+0xac/0xe4
[   72.229621] [<801e8a84>] bus_probe_device+0x3c/0xb0
[   72.234570] [<801e6d68>] device_add+0x444/0x550
[   72.239178] [<8022cb38>] usb_set_configuration+0x5e8/0x634
[   72.244756] [<802359a0>] generic_probe+0x6c/0x9c
[   72.249452] [<801e9824>] driver_probe_device+0x1fc/0x2c4
[   72.254841] [<801e7c84>] bus_for_each_drv+0x9c/0xac
[   72.259800] [<801e95d4>] __device_attach+0xac/0xe4
[   72.264661] [<801e8a84>] bus_probe_device+0x3c/0xb0
[   72.269619] [<801e6d68>] device_add+0x444/0x550
[   72.274221] [<802246ec>] usb_new_device+0x218/0x344
[   72.279182] [<802256bc>] hub_event+0xc48/0xe84
[   72.283705] [<800371a4>] process_one_work+0x1e8/0x318
[   72.288843] [<80037fc8>] worker_thread+0x2f4/0x424
[   72.293708] [<8003c940>] kthread+0x130/0x138
[   72.298054] [<800092d8>] ret_from_kernel_thread+0x14/0x1c
[   72.303531] ---[ end trace e5f3e34a9f1d79f7 ]---
[   72.308231] ------------[ cut here ]------------
[   72.312928] WARNING: CPU: 0 PID: 347 at drivers/usb/core/hcd.c:1595 usb_hcd_map_urb_for_dma+0x3f4/0x524
[   72.322455] transfer buffer not dma capable
[   72.326696] Modules linked in: pppoe ppp_async pppox ppp_generic nf_conntrack_ipv6 lzo iptable_nat ipt_REJECT ipt_MASQUERADE xt_time xt_tcpudp xt_state xt_nat xt_multiport xt_mark xt_mac xt_limit xt_conntrack xt_comment xt_TCPMSS xt_REDIRECT xt_LOG xt_FLOWOFFLOAD slhc nf_reject_ipv4 nf_nat_redirect nf_nat_masquerade_ipv4 nf_conntrack_ipv4 nf_nat_ipv4 nf_nat nf_log_ipv4 nf_flow_table_hw nf_flow_table nf_defrag_ipv6 nf_defrag_ipv4 nf_conntrack_rtcache nf_conntrack lzo_decompress lzo_compress iptable_mangle iptable_filter ip_tables crc_ccitt mt7628 i2c_mt7621 snd_soc_core ralink_gdma virt_dma i2c_dev ip6t_REJECT nf_reject_ipv6 nf_log_ipv6 nf_log_common ip6table_mangle ip6table_filter ip6_tables x_tables snd_compress snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_rawmidi snd_seq_device snd_hwdep snd
[   72.398434]  input_core soundcore vfat fat nls_utf8 nls_iso8859_1 nls_cp437 regmap_spi regmap_i2c i2c_core crypto_acompress mmc_block usb_storage mtk_sd mmc_core leds_gpio ohci_platform ohci_hcd ehci_platform sd_mod scsi_mod ehci_hcd gpio_button_hotplug
[   72.421261] CPU: 0 PID: 347 Comm: kworker/0:3 Tainted: G        W       4.14.50 #0
[   72.428952] Workqueue: usb_hub_wq hub_event
[   72.433200] Stack : 86846000 804635c8 86846610 8004e674 87e2b454 80447aa7 803f1944 0000015b
[   72.441699]         803f18b0 87f518b4 86846000 8004f350 86846610 87fd3915 87f51890 24c668a7
[   72.450196]         00000000 00000000 00000000 000000ec 00000000 65756575 7375203a 75685f62
[   72.458691]         00000001 00000000 f8000000 63686520 00000000 00000000 802279e8 80412a8c
[   72.467187]         00000009 0000063b 86846000 804635c8 00000002 801db240 00000000 804a0000
[   72.475671]         ...
[   72.478159] Call Trace:
[   72.480657] [<8000e424>] show_stack+0x74/0x104
[   72.485183] [<800245a0>] __warn+0x110/0x118
[   72.489441] [<800245d8>] warn_slowpath_fmt+0x30/0x3c
[   72.494490] [<802279e8>] usb_hcd_map_urb_for_dma+0x3f4/0x524
[   72.500243] [<80228d30>] usb_hcd_submit_urb+0x79c/0x7d0
[   72.505546] [<8022a2c0>] usb_start_wait_urb+0x5c/0xec
[   72.510688] [<801c4d24>] fbusb_probe+0x288/0x2bc
[   72.515378] [<8022dd48>] usb_probe_interface+0x1cc/0x1f4
[   72.520788] [<801e9824>] driver_probe_device+0x1fc/0x2c4
[   72.526186] [<801e7c84>] bus_for_each_drv+0x9c/0xac
[   72.531135] [<801e95d4>] __device_attach+0xac/0xe4
[   72.536007] [<801e8a84>] bus_probe_device+0x3c/0xb0
[   72.540957] [<801e6d68>] device_add+0x444/0x550
[   72.545554] [<8022cb38>] usb_set_configuration+0x5e8/0x634
[   72.551139] [<802359a0>] generic_probe+0x6c/0x9c
[   72.555838] [<801e9824>] driver_probe_device+0x1fc/0x2c4
[   72.561227] [<801e7c84>] bus_for_each_drv+0x9c/0xac
[   72.566186] [<801e95d4>] __device_attach+0xac/0xe4
[   72.571058] [<801e8a84>] bus_probe_device+0x3c/0xb0
[   72.576014] [<801e6d68>] device_add+0x444/0x550
[   72.580615] [<802246ec>] usb_new_device+0x218/0x344
[   72.585564] [<802256bc>] hub_event+0xc48/0xe84
[   72.590103] [<800371a4>] process_one_work+0x1e8/0x318
[   72.595233] [<80037fc8>] worker_thread+0x2f4/0x424
[   72.600108] [<8003c940>] kthread+0x130/0x138
[   72.604445] [<800092d8>] ret_from_kernel_thread+0x14/0x1c
[   72.609929] ---[ end trace e5f3e34a9f1d79f8 ]---

No idea what is wrong…have to read more code and compare. At least usb-storage is working normal, if that works, it means this usb driver should be no big issue.

fbusb is just a USB device that to map a virtual frame buffer, I thought it is easy to be done 🙂

Weird Issue when Develop Frame buffer Driver

I meet a ghost bug, this almost kills me…
The source code is as simple as the following:

struct fbusb_par {
	struct usb_interface *interface;
	u32 palette[PSEUDO_PALETTE_SIZE];
};

static int fbusb_probe(struct usb_interface *interface,
		       const struct usb_device_id *id)
{
	struct fb_info *info;
	info = framebuffer_alloc(sizeof(struct fbusb_par), &interface->dev);
        if (!info)
               return -ENOMEM;

	par = info->par;
	par->interface = interface;

	return 0;
}

static void fbusb_disconnect(struct usb_interface *interface)
{
	dev_info(&interface->dev,
		 "framebuffer device now disconnected.\n");
}

static const struct usb_device_id fbusb_ids[] = {
	{ USB_DEVICE(0x04b4, 0x1004) },
	{ }
};
MODULE_DEVICE_TABLE(usb, fbusb_ids);

static struct usb_driver fbusb_driver = {
	.name = "fbusb",
	.probe = fbusb_probe,
	.disconnect = fbusb_disconnect,
	.id_table = fbusb_ids,
};

module_usb_driver(fbusb_driver);

The mysterious bug is this driver crashed at par->interface = interface; and after debug, par is a null pointer, but info is not a null pointer! Let’s check framebuffer_alloc source code, if return info is correct, there is no way par to be null pointer.

struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
{
#define BYTES_PER_LONG (BITS_PER_LONG/8)
#define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG))
	int fb_info_size = sizeof(struct fb_info);
	struct fb_info *info;
	char *p;

	if (size)
		fb_info_size += PADDING;

	p = kzalloc(fb_info_size + size, GFP_KERNEL);

	if (!p)
		return NULL;

	info = (struct fb_info *) p;

	if (size)
		info->par = p + fb_info_size;

	info->device = dev;

#ifdef CONFIG_FB_BACKLIGHT
	mutex_init(&info->bl_curve_mutex);
#endif

	return info;
#undef PADDING
#undef BYTES_PER_LONG
}
EXPORT_SYMBOL(framebuffer_alloc);

Also step into this framebuffer_alloc function, in this function info->par is not null and its value is correct. So what is happening once info returned? who changed info->par to null? This is really weird bug…I have never seen such thing before.

PS: I guess I find the problem. If I put the source into Linux source code, it will report some .ko is missing, but if I move it to package/kernel as a package, it will happen that weird problem. So it is package missing problem.

VoCore2 Screen: new firmware

After many weeks struggle, finally I finish the new firmware for the screen, this new firmware mainly improve the boot up speed of the screen, old one takes six seconds, new ones less than one. Also add control function to modify backlight strength and support 8bit/16bit/24bit pixel format.

Based on this firmware, now we can have:

1. Linux text console which is based on frame buffer 16bit or 32bit, old firmware only support 24bit.

2. super smooth games from GBA, NES, GEONEO. We support 8bit mode, now we have more CPU for game logic but not for screen data transfer.

3. smooth games from DOS. DOS games such as DOOM will be faster, such game 12fps is playable, new firmware will make it at least 15fps.

4. control rotate the screen, backlight.

The main optimize is for VoCore2 or other embed device with USB port but no display port such as HDMI. This solution will greatly save cost. For example, a chip with display port normally is over 5USD, it is not included DDR and flash yet, full solution with wifi, ethernet should be around 35USD, a screen with HDMI is around 25USD. So mass production is 60USD/pcs 10K unit.

For VoCore2 solution, only 33.99 + 17.99 = 52USD, this is just sample price! 🙂 mass production(1K unit) normally have 40% discount, totally cost should be around 30USD, only half!

What you will get for 30USD? 580MHz Linux based computer + 5 x 100Mbps ethernet + 150Mbps wifi + smooth UI display. It is fit for the control system, education toy solution for kids, also a good replace STM32 or RaspberryPi.

Linux console driver will be released in next week, need more hard work, I am enjoying it 🙂

VoCore2: alsa driver patch 1

Finally I recover from the fever, so happy back to work 🙂

Combine VoCore2 Ultimate firmware to latest openwrt is always one of my dream. Today I start first step.

VoCore2 ultimate has one driver is different than the single board version, it is ES8388 codec driver, but limited to my patch skill, it is so hard for me to patch it to openwrt system. After port mediatek wireless driver, I understand some of the secret now, so I can push the first version of es8388 driver to github/vonger/vocore2.

Compose

this patch has four files, 810,811 used to patch linux kernel, put it into openwrt/target/linux/ramips/patch 4.14/ then it should work. 811 is used to fix pinctrl driver, because refclk this name has used in many places, if we do not change the name, it will conflict with function named refclk. This patch I will try to submit to openwrt later, it is a bug. 🙂

rest is dts, VOCORE2.dtsi I change refclk pinmux from gpio to gpio refclk, so gpio0 pin will work as 12MHz clock.

PS: gpio0 is not real GPIO 0, it is actually GPIO 11 in register, nobody knows why ralink engineer named it gpio0, you can check its datasheet, really mess :p

How to use?

after patch everything and use the new dts then compile and flash to V2U(a lot of work), you can now try it.

But as I said, this is not a stable driver…es8388 driver is acting weird because I am a noob of alsa. I have to left some back door for hack. 🙂

in /sys/devices/platform/i2c-gpio/i2c-0/0-0010/ there are two file node named i2cread and i2cwrite, used to directly write to es8388 i2c driver and control the codec directly.

Before you use aplay xxx.wav play some sound, please run this command:

echo enable left mixer.
echo 2780 > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite
echo enable right mixer.
echo 2a80 > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite

echo 1a00 > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite
echo 1b00 > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite
echo 2e1e > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite
echo 2f1e > /sys/devices/platform/i2c-gpio/i2c-0/0-0010/i2cwrite

first four lines are used to fix the wired bug, maybe my dts sound path setting is not correct cause this problem…(but everything looks correct for me)
second four lines are used to set the volume of left channel/right channel to max, careful your ear! 🙂

PSS: second four lines because I can not find a way to raise volume in aplay, in madplay volume works normal, if you use madplay, ignore those four lines.

My compiled firmware, just for test: http://vonger.cn/misc/vocore2/20181010-AUDIOTEST.bin

PSSS: recently github transfer speed is really fast, normally only 100KB/s, have to wait almost two hours…lol, should we thanks to Microsoft?

 

VoCore2: ethernet without transformer

note: Recently my team and myself are all sick… some packages shipping are delay. We will handle them in this week.

Some people on forum ask about this, this is my working solution to connect ethernet with VoCore2 P0 port. I have tried my best to make it simple, but only this way works.

It require at least eight 100nF cap at 50V(depends on your usage), also eight 49.9ohm resistor.

Currently I have done a new version of VoCore2, it has a USB to ethernet and one microSD slot. just want to make it thiner and easy to use.


PS:new version of VoCore2 now is using 0201 instead of 0402 for RF part. Its signal is better.

UBOOT: fix brick by UART + Ethernet

It is very slow to upload firmware by “0: Load system code then write to Flash via SERIAL.”

I find another way, “8: Start Web Server to load system code.”, only take few seconds(40~60s).

Here is its log 🙂 Anyway we do not need to care about it, only need to press 8 at start up.


After press 8, we can connect to VoCore uboot web page from remote computer now. Make sure your computer and VoCore are connected by ethernet cable.

Your computer side: need to setup your computer ip address to 192.168.1.100, mask 255.255.255.0 and default gateway to 192.168.1.123, remember disable DHCP and setup manually.

(Here miss some pictures, clever reader please help yourself)

Then open browser to address 192.168.1.123, you will see the upgrade page, choose upgrade file(normally VoCore2 upgrade firmware named YYYYmmdd(V).bin) then click on “Upload”(on VoCore2 part it will show Loading … and its progress), around 1minute, load done and VoCore will reboot automatically.

(Here also miss some pictures … it is late here, sweet bed … )

Good Luck :’)

 

PS: the original web upgrade page is ugly, I will try to make it better ( for me, at least )

Patch LuCI for VoCore2

Firmware link: http://vonger.cn/misc/vocore2/20180723V.bin

1. Click on “Scan”, it will show nearby access point, this mode is STA only, better to setting up in Point 2 to enable AP + STA.

2. Click Point 2, go to wireless setting.

In “General Setup” page, input your AP SSID.

Then in “Wireless Security”, setup your password, currently only WPA2 supported.

3. After that, click “Save & Apply”, then enable STA mode, wait around 10 seconds, setting up completed, now your VoCore can access internet.

mt76 or mt7628?

Currently openwrt has an opensource driver mt76, I have a study about it, every line of its code is very clear and beautiful, so it should be easy to replace official mt7628 with this one, unfortunately, I find it is very hard to understand its registers(mtk did not document any of that registers) so I can not setting up its interfaces unless do some hack 🙂

There is another way, enable cfg80211 in mt7628, I find it has some code about cfg80211, but I enable it in makefile, it can not work at all 🙂 guess it is not well tested…

VoCore2: LuCI

Setting STA mode by LuCI is always my target.

Spend some time learn about LuCI.

First fix is about the encryption:
Currently the encrypt do not have WPA/WPA2, it is because in /usr/lib/lua/luci/model/cbi/admin_network/wifi.lua:663, we should add hwtype=ralink to enable the encrypt ways.

Note: it only have hwtype == mac80211 or hwtype == broadcom, but no ralink, so we can not find WPA/WPA2 encryption and can not setup its password. I have submitted this patch to github/openwrt/luci, hope this can be fixed.

Second fix is about the scan:

This needs to rewrite iwinfo_wext_scan.c in libiwinfo.
Anyway, we can not use that “Join Network” button, because LuCI action/design is very weird, it will remove exists AP setting…and no way set it to “apcli0”.
There is an easy way to connect to STA, directly setting up client and it will be done.

My home router name is KOKO, so ESSID is KOKO, BSSID empty. Network already in setting, then select “Wireless Security” input your password.