2011/08/17

Android上的LAN device

最近要在Android上加LAN device support,該LAN device 是USB interface的SMSC9514。

ifconfig


adb shell後用以下指令可以看到目前板子上的網路裝置
# busybox-armv6l ifconfig -a

busybox可自行上網下載執行檔

ifconfig 運作方式


追busybox的code可以找到這段程式

// file: busybox-1.18.4/networking/interface.c
#define _PATH_PROCNET_DEV               "/proc/net/dev"

static int if_readlist_proc(char *target)
{
	static smallint proc_read;

	FILE *fh;
	char buf[512];
	struct interface *ife;
	int err, procnetdev_vsn;

	if (proc_read)
		return 0;
	if (!target)
		proc_read = 1;

	fh = fopen_or_warn(_PATH_PROCNET_DEV, "r");
	if (!fh) {
		return if_readconf();
	}

可以看到它open了一個檔案_PATH_PROCNET_DEV,這個檔案為"/proc/net/dev",所以得知ifconfig是從那裡抓network devices name

driver


秀出/proc/net/dev訊息


至於driver如何將這些資訊秀出可以參考 dev_seq_show() 如下

// file: kernel/net/core/dev.c
static void dev_seq_printf_stats(struct seq_file *seq, struct net_device *dev)
{
	struct rtnl_link_stats64 temp;
	const struct rtnl_link_stats64 *stats = dev_get_stats(dev, &temp);

	seq_printf(seq, "%6s: %7llu %7llu %4llu %4llu %4llu %5llu %10llu %9llu "
		   "%8llu %7llu %4llu %4llu %4llu %5llu %7llu %10llu\n",
		   dev->name, stats->rx_bytes, stats->rx_packets,
		   stats->rx_errors,
		   stats->rx_dropped + stats->rx_missed_errors,
		   stats->rx_fifo_errors,
		   stats->rx_length_errors + stats->rx_over_errors +
		    stats->rx_crc_errors + stats->rx_frame_errors,
		   stats->rx_compressed, stats->multicast,
		   stats->tx_bytes, stats->tx_packets,
		   stats->tx_errors, stats->tx_dropped,
		   stats->tx_fifo_errors, stats->collisions,
		   stats->tx_carrier_errors +
		    stats->tx_aborted_errors +
		    stats->tx_window_errors +
		    stats->tx_heartbeat_errors,
		   stats->tx_compressed);
}

/*
 *	Called from the PROCfs module. This now uses the new arbitrary sized
 *	/proc/net interface to create /proc/net/dev
 */
static int dev_seq_show(struct seq_file *seq, void *v)
{
	if (v == SEQ_START_TOKEN)
		seq_puts(seq, "Inter-|   Receive                            "
			      "                    |  Transmit\n"
			      " face |bytes    packets errs drop fifo frame "
			      "compressed multicast|bytes    packets errs "
			      "drop fifo colls carrier compressed\n");
	else
		dev_seq_printf_stats(seq, v);
	return 0;
}

driver註冊network device


driver要跟kernel註冊自己是個network device,註冊時最底層是用到 list_netdevice

// file: kernel/net/core/dev.c
/* Device list insertion */
static int list_netdevice(struct net_device *dev)
{
	struct net *net = dev_net(dev);

	ASSERT_RTNL();

	write_lock_bh(&dev_base_lock);
	list_add_tail_rcu(&dev->dev_list, &net->dev_base_head);
	hlist_add_head_rcu(&dev->name_hlist, dev_name_hash(net, dev->name));
	hlist_add_head_rcu(&dev->index_hlist,
			   dev_index_hash(net, dev->ifindex));
	write_unlock_bh(&dev_base_lock);
	return 0;
}

最外層是用

// file: kernel/drivers/net/usb/usbnet.c
int
usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
{
	status = register_netdev (net);

usbnet_probe又是誰呼叫了,我們就是我們要用的LAN chip SMSC95XX用到了

// file: kernel/drivers/net/usb/smsc95xx.c
static struct usb_driver smsc95xx_driver = {
	.name		= "smsc95xx",
	.id_table	= products,
	.probe		= usbnet_probe,
	.suspend	= usbnet_suspend,
	.resume		= usbnet_resume,
	.disconnect	= usbnet_disconnect,
};

SMSC9514

# $ adb shell
# lsusb
1d6b:0002 (bus 1, device 1)
1d6b:0002 (bus 2, device 1)
# # 插入裝置
# lsusb
1d6b:0002 (bus 1, device 1)
1d6b:0002 (bus 2, device 1)
0424:9514 (bus 1, device 2)
0424:ec00 (bus 1, device 3)
# busybox-armv6l ash
/ # # 設IP跟DNS
/ # busybox-armv6l ifconfig eth0 192.168.1.123
/ # busybox-armv6l route add default gw 192.168.1.1
/ # ping 168.95.1.1
PING 168.95.1.1 (168.95.1.1) 56(84) bytes of data.
64 bytes from 168.95.1.1: icmp_seq=1 ttl=242 time=670 ms
64 bytes from 168.95.1.1: icmp_seq=2 ttl=242 time=989 ms
64 bytes from 168.95.1.1: icmp_seq=3 ttl=242 time=589 ms
#setprop net.dns1 168.95.1.1

UI


這部分比較麻煩,可以自行參考android-x86的實作。

No comments: