您尚未登录。

#1 Re: 全志 SOC » 全志H3 找不到Mali-400 GPU设备 » 2023-03-30 13:32:43

按老夫多年的经验,别去玩主线Linux

#2 Re: DIY/综合/Arduino/写字机/3D打印机/智能小车/平衡车/四轴飞行/MQTT/物联网 » C 网络编程 » 2023-03-15 21:43:36

https://stackoverflow.com/questions/13140753/binding-with-wifi-interface-in-linux

binding with wifi interface in linux


if (getifaddrs(&ifaddrs) < 0) {
my_loge(CRIT, "address detection failed");
return(0);
}

// zero
count = 0;

// unset all but CAP_HOST and CAP_ROUTER
sysinfo->cap &= (CAP_HOST|CAP_ROUTER);
sysinfo->cap_active &= (CAP_HOST|CAP_ROUTER);
// reset counter
sysinfo->physif_count = 0;

// mark all interfaces
TAILQ_FOREACH(netif, netifs, entries) {
netif->type = NETIF_OLD;
}

for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {

// skip interfaces without addresses
if (ifaddr->ifa_addr == NULL) {
    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
    continue;
}

// only handle datalink addresses
if (ifaddr->ifa_addr->sa_family != NETIF_AF)
    continue;

// prepare ifr struct
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifaddr->ifa_name, sizeof(ifr.ifr_name));


// skip non-ethernet interfaces
memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));
if (saddrll.sll_hatype != ARPHRD_ETHER) {
    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
    continue;
}
index = saddrll.sll_ifindex;
memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));
if ((saddrdl.sdl_type != IFT_BRIDGE) &&
    (saddrdl.sdl_type != IFT_ETHER)) {
if (saddrdl.sdl_type != IFT_ETHER) {
    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
    continue;
}
index = saddrdl.sdl_index;

// check for interfaces that are down
enabled = 0;
if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0)
    enabled = (ifr.ifr_flags & IFF_UP);

// detect interface type
type = netif_type(sockfd, index, ifaddr, &ifr);

if (type == NETIF_REGULAR) { 
    my_log(INFO, "found ethernet interface %s", ifaddr->ifa_name);
    sysinfo->physif_count++;
} else if (type == NETIF_WIRELESS) {
    my_log(INFO, "found wireless interface %s", ifaddr->ifa_name);
    sysinfo->cap |= CAP_WLAN;
    sysinfo->cap_active |= (enabled == 1) ? CAP_WLAN : 0;
} else if (type == NETIF_TAP) {
    my_log(INFO, "found tun/tap interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BONDING) {
    my_log(INFO, "found bond interface %s", ifaddr->ifa_name);
} else if (type == NETIF_BRIDGE) {
    my_log(INFO, "found bridge interface %s", ifaddr->ifa_name);
    sysinfo->cap |= CAP_BRIDGE; 
    sysinfo->cap_active |= (enabled == 1) ? CAP_BRIDGE : 0;
} else if (type == NETIF_VLAN) {
    my_log(INFO, "found vlan interface %s", ifaddr->ifa_name);
} else if (type == NETIF_INVALID) {
    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
    continue;
}

https://raw.githubusercontent.com/sspans/ladvd/master/src/netif.c

/*
 * $Id$
 *
 * Copyright (c) 2008, 2009, 2010
 *      Sten Spans <sten@blinkenlights.nl>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "common.h"
#include "util.h"
#include "proto/lldp.h"

#include <ifaddrs.h>
#include <dirent.h>
#include <ctype.h>

#if HAVE_ASM_TYPES_H
#include <asm/types.h>
#endif /* HAVE_ASM_TYPES_H */

#if HAVE_LINUX_SOCKIOS_H
#include <linux/sockios.h>
#endif /* HAVE_LINUX_SOCKIOS_H */

#if HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif /* HAVE_SYS_SOCKIO_H */

#ifdef HAVE_NETPACKET_PACKET_H
#include <netpacket/packet.h>
#endif /* HAVE_NETPACKET_PACKET_H */

#ifdef HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif /* HAVE_NET_IF_DL_H */

#ifdef HAVE_NET_IF_TYPES_H
#include <net/if_types.h>
#endif /* HAVE_NET_IF_TYPES_H */


#ifdef AF_PACKET
#define NETIF_AF    AF_PACKET
#elif defined(AF_LINK)
#define NETIF_AF    AF_LINK
#endif

static int sockfd = -1;

static void netif_addrs(struct ifaddrs *, struct nhead *, struct my_sysinfo *);

#if defined(NETIF_LINUX)
#include "netif_linux.c"
#elif defined(NETIF_BSD)
#include "netif_bsd.c"
#endif

void netif_init() {
    if (sockfd == -1)
	sockfd = my_socket(AF_INET, SOCK_DGRAM, 0);
}

// create netifs for a list of interfaces
uint16_t netif_fetch(int ifc, char *ifl[], struct my_sysinfo *sysinfo,
		    struct nhead *netifs) {

    struct ifaddrs *ifaddrs, *ifaddr = NULL;
    struct ifreq ifr;
    int count = 0;
    int type, enabled;
    uint32_t index;
    struct parent_req mreq = {};

#ifdef AF_PACKET
    struct sockaddr_ll saddrll;
#elif defined(AF_LINK)
    struct sockaddr_dl saddrdl;
#endif

    // netifs
    struct netif *n_netif, *netif = NULL;

    if (sockfd == -1)
	my_fatal("please call netif_init first");

    if (getifaddrs(&ifaddrs) < 0) {
	my_loge(CRIT, "address detection failed");
	return(0);
    }

    // zero
    count = 0;

    // unset all but CAP_HOST and CAP_ROUTER
    sysinfo->cap &= (CAP_HOST|CAP_ROUTER);
    sysinfo->cap_active &= (CAP_HOST|CAP_ROUTER);
    // reset counter
    sysinfo->physif_count = 0;

    // mark all interfaces
    TAILQ_FOREACH(netif, netifs, entries) {
	netif->type = NETIF_OLD;
    }

    for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {

	// skip interfaces without addresses
	if (ifaddr->ifa_addr == NULL) {
	    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
	    continue;
	}

	// only handle datalink addresses
	if (ifaddr->ifa_addr->sa_family != NETIF_AF)
	    continue;

	// prepare ifr struct
	memset(&ifr, 0, sizeof(ifr));
	strlcpy(ifr.ifr_name, ifaddr->ifa_name, sizeof(ifr.ifr_name));


	// skip non-ethernet interfaces
#ifdef AF_PACKET
	memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));
	if (saddrll.sll_hatype != ARPHRD_ETHER) {
	    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
	    continue;
	}
	index = saddrll.sll_ifindex;
#elif defined(AF_LINK)
	memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));
#ifdef IFT_BRIDGE
	if ((saddrdl.sdl_type != IFT_BRIDGE) &&
	    (saddrdl.sdl_type != IFT_ETHER)) {
#else
	if (saddrdl.sdl_type != IFT_ETHER) {
#endif
	    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
	    continue;
	}
	index = saddrdl.sdl_index;
#endif

	// check for interfaces that are down
	enabled = 0;
	if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) >= 0)
	    enabled = (ifr.ifr_flags & IFF_UP);

	// detect interface type
	type = netif_type(sockfd, index, ifaddr, &ifr);

	if (type == NETIF_REGULAR) { 
	    my_log(INFO, "found ethernet interface %s", ifaddr->ifa_name);
	    sysinfo->physif_count++;
	} else if (type == NETIF_WIRELESS) {
	    my_log(INFO, "found wireless interface %s", ifaddr->ifa_name);
	    sysinfo->cap |= CAP_WLAN;
	    sysinfo->cap_active |= (enabled == 1) ? CAP_WLAN : 0;
	} else if (type == NETIF_TAP) {
	    my_log(INFO, "found tun/tap interface %s", ifaddr->ifa_name);
	} else if (type == NETIF_TEAMING) {
	    my_log(INFO, "found teaming interface %s", ifaddr->ifa_name);
	} else if (type == NETIF_BONDING) {
	    my_log(INFO, "found bond interface %s", ifaddr->ifa_name);
	} else if (type == NETIF_BRIDGE) {
	    my_log(INFO, "found bridge interface %s", ifaddr->ifa_name);
	    sysinfo->cap |= CAP_BRIDGE; 
	    sysinfo->cap_active |= (enabled == 1) ? CAP_BRIDGE : 0;
	} else if (type == NETIF_VLAN) {
	    my_log(INFO, "found vlan interface %s", ifaddr->ifa_name);
	} else if (type == NETIF_INVALID) {
	    my_log(INFO, "skipping interface %s", ifaddr->ifa_name);
	    continue;
	}


	// skip interfaces that are down
	if (enabled == 0) {
	    my_log(INFO, "skipping interface %s (down)", ifaddr->ifa_name);
	    continue;
	}


	my_log(INFO, "adding interface %s", ifaddr->ifa_name);

	// fetch / create netif
	if ((netif = netif_byindex(netifs, index)) == NULL) {
	    netif = my_malloc(sizeof(struct netif));
	    TAILQ_INSERT_TAIL(netifs, netif, entries);
	} else {
	    // reset everything up to the tailq_entry but keep protos
	    uint16_t protos = netif->protos;
	    memset(netif, 0, offsetof(struct netif, entries));
	    netif->protos = protos;
	}

        // copy name, index and type
	netif->index = index;
	strlcpy(netif->name, ifaddr->ifa_name, sizeof(netif->name));
	netif->type = type;

#ifdef HAVE_SYSFS
	mreq.op = PARENT_ALIAS;
	mreq.index = netif->index;

	if (my_mreq(&mreq))
	    strlcpy(netif->description, mreq.buf, IFDESCRSIZE);
#elif defined(SIOCGIFDESCR)
#ifndef __FreeBSD__
	ifr.ifr_data = (caddr_t)&netif->description;
#else
	ifr.ifr_buffer.buffer = &netif->description;
	ifr.ifr_buffer.length = IFDESCRSIZE;
#endif
	ioctl(sockfd, SIOCGIFDESCR, &ifr);
#endif

	if (sysinfo->mifname && (strcmp(netif->name, sysinfo->mifname) == 0))
	    sysinfo->mnetif = netif;

	// update counters
	count++;
    }

    // remove old interfaces
    TAILQ_FOREACH_SAFE(netif, netifs, entries, n_netif) {
	if (netif->type != NETIF_OLD)
	    continue;

	my_log(INFO, "removing old interface %s", netif->name);

	mreq.op = PARENT_CLOSE;
	mreq.index = netif->index;
	my_mreq(&mreq);

	TAILQ_REMOVE(netifs, netif, entries);
	if (sysinfo->mnetif == netif)
	    sysinfo->mnetif = NULL;
	free(netif);
    }

    // add child subif lists to each bond/bridge
    // detect vlan interface settings
    TAILQ_FOREACH(netif, netifs, entries) {
	my_log(INFO, "detecting %s settings", netif->name);
	switch(netif->type) {
#ifdef HAVE_LIBTEAM
	    case NETIF_TEAMING:
		netif_team(sockfd, netifs, netif, &ifr);
		break;
#endif /* HAVE_LIBTEAM */
	    case NETIF_BONDING:
		netif_bond(sockfd, netifs, netif, &ifr);
		break;
	    case NETIF_BRIDGE:
		netif_bridge(sockfd, netifs, netif, &ifr);
		break;
	    case NETIF_VLAN:
		netif_vlan(sockfd, netifs, netif, &ifr);
		break;
	    case NETIF_REGULAR:
		netif_device_id(sockfd, netif, &ifr);
		break;
	    default:
		break;
	}
    }

    // add addresses to netifs
    my_log(INFO, "fetching addresses for all interfaces");
    netif_addrs(ifaddrs, netifs, sysinfo);

    // use the first mac as chassis id
    if ((netif = TAILQ_FIRST(netifs)) != NULL)
	memcpy(&sysinfo->hwaddr, &netif->hwaddr, ETHER_ADDR_LEN);

    // validate detected interfaces
    if (ifc > 0) {
	count = 0;

	for (int j = 0; j < ifc; j++) {
	    netif = netif_byname(netifs, ifl[j]);
	    if (netif == NULL) {
		my_log(CRIT, "interface %s is invalid", ifl[j]);
	    } else if (netif->type == NETIF_VLAN) {
		my_log(CRIT, "vlan interface %s is not supported", ifl[j]);
	    } else {
		netif->argv = 1;
		count++;
	    }
	}
	if (count != ifc)
	    count = 0;

    } else if (count == 0) {
	my_log(CRIT, "no valid interface found");
    }

    if ((options & OPT_MNETIF) && !sysinfo->mnetif)
	my_log(CRIT, "could not detect the specified management interface");

    // cleanup
    freeifaddrs(ifaddrs);

    return(count);
};


// perform address detection for all netifs
static void netif_addrs(struct ifaddrs *ifaddrs, struct nhead *netifs,
		struct my_sysinfo *sysinfo) {
    struct ifaddrs *ifaddr;
    struct netif *netif, *mnetif;

    struct sockaddr_in saddr4;
    struct sockaddr_in6 saddr6;
#ifdef AF_PACKET
    struct sockaddr_ll saddrll;
#endif
#ifdef AF_LINK
    struct sockaddr_dl saddrdl;
#endif

    for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {

	// skip interfaces without addresses
	if (ifaddr->ifa_addr == NULL)
	    continue;

	// fetch the netif for this ifaddr
	netif = netif_byname(netifs, ifaddr->ifa_name);
	if (netif == NULL)
	    continue;

	if (ifaddr->ifa_addr->sa_family == AF_INET) {
	    if (netif->ipaddr4 != 0)
		continue;

	    // alignment
	    memcpy(&saddr4, ifaddr->ifa_addr, sizeof(saddr4));

	    memcpy(&netif->ipaddr4, &saddr4.sin_addr,
		  sizeof(saddr4.sin_addr));

	    // detect mnetif
	    if (sysinfo->mnetif || (sysinfo->maddr4 == 0))
		continue;

	    if (sysinfo->maddr4 == netif->ipaddr4)
		sysinfo->mnetif = netif;

	} else if (ifaddr->ifa_addr->sa_family == AF_INET6) {
	    if (!IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)netif->ipaddr6))
		continue;

	    // alignment
	    memcpy(&saddr6, ifaddr->ifa_addr, sizeof(saddr6));

	    // skip link-local
	    if (IN6_IS_ADDR_LINKLOCAL(&saddr6.sin6_addr))
		continue;

	    memcpy(&netif->ipaddr6, &saddr6.sin6_addr,
		  sizeof(saddr6.sin6_addr));

	    // detect mnetif
	    if (sysinfo->mnetif ||
		(IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)sysinfo->maddr6)))
		continue;

	    if (memcmp(&sysinfo->maddr6, &netif->ipaddr6,
			sizeof(sysinfo->maddr6)) == 0)
		sysinfo->mnetif = netif;
#ifdef AF_PACKET
	} else if (ifaddr->ifa_addr->sa_family == AF_PACKET) {

	    // alignment
	    memcpy(&saddrll, ifaddr->ifa_addr, sizeof(saddrll));

	    memcpy(&netif->hwaddr, &saddrll.sll_addr, ETHER_ADDR_LEN);
#endif
#ifdef AF_LINK
	} else if (ifaddr->ifa_addr->sa_family == AF_LINK) {

	    // alignment
	    memcpy(&saddrdl, ifaddr->ifa_addr, sizeof(saddrdl));

	    memcpy(&netif->hwaddr, LLADDR(&saddrdl), ETHER_ADDR_LEN);
#endif
	}
    }

    // return when no management netif is available
    if (!(options & OPT_MADDR) || !sysinfo->mnetif)
	return;
    mnetif = sysinfo->mnetif;

    // use management address when requested
    TAILQ_FOREACH(netif, netifs, entries) {
	netif->ipaddr4 = mnetif->ipaddr4;
	memcpy(&netif->ipaddr6, &mnetif->ipaddr6, sizeof(mnetif->ipaddr6));
    }
}


// perform media detection on physical interfaces
int netif_media(struct netif *netif) {

    struct ifreq ifr = {};

    if (sockfd == -1)
	my_fatal("please call netif_init first");

    netif->duplex = -1;
    netif->autoneg_supported = -1;
    netif->autoneg_enabled = -1;
    netif->autoneg_pmd = 0;
    netif->mau = 0;

    strlcpy(ifr.ifr_name, netif->name, sizeof(ifr.ifr_name));

    // interface mtu
    if (ioctl(sockfd, SIOCGIFMTU, (caddr_t)&ifr) >= 0)
	netif->mtu = ifr.ifr_mtu;
    else
	my_log(INFO, "mtu detection failed on interface %s", netif->name);

    // the rest only makes sense for real interfaces
    if (netif->type != NETIF_REGULAR)
	return(EXIT_SUCCESS);

    netif_physical(sockfd, netif);

    return(EXIT_SUCCESS);
}

#3 Re: DIY/综合/Arduino/写字机/3D打印机/智能小车/平衡车/四轴飞行/MQTT/物联网 » C 网络编程 » 2023-03-15 11:45:52

How can I enumerate the list of network devices or interfaces in C or C++ in FreeBSD ?

I want a list like "ue0", "ath0", "wlan0".

I've been looking though the ifconfig(1) code but its not clear at all where the task is being performed.

I'll happily take an answer, a pointer to a man page, or a link to the appropriate line in ifconfig. I may have just missed it.

#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <arpa/inet.h>

int main(void)
{
    char          buf[1024];
    struct ifconf ifc;
    struct ifreq *ifr;
    int           sck;
    int           nInterfaces;
    int           i;

/* Get a socket handle. */
    sck = socket(AF_INET, SOCK_DGRAM, 0);
    if(sck < 0)
    {
        perror("socket");
        return 1;
    }

/* Query available interfaces. */
    ifc.ifc_len = sizeof(buf);
    ifc.ifc_buf = buf;
    if(ioctl(sck, SIOCGIFCONF, &ifc) < 0)
    {
        perror("ioctl(SIOCGIFCONF)");
        return 1;
    }

/* Iterate through the list of interfaces. */
    ifr         = ifc.ifc_req;
    nInterfaces = ifc.ifc_len / sizeof(struct ifreq);
    for(i = 0; i < nInterfaces; i++)
    {
        struct ifreq *item = &ifr[i];

    /* Show the device name and IP address */
        printf("%s: IP %s",
               item->ifr_name,
               inet_ntoa(((struct sockaddr_in *)&item->ifr_addr)->sin_addr));


    /* Get the broadcast address (added by Eric) */
        if(ioctl(sck, SIOCGIFBRDADDR, item) >= 0)
            printf(", BROADCAST %s", inet_ntoa(((struct sockaddr_in *)&item->ifr_broadaddr)->sin_addr));
        printf("\n");
    }

        return 0;
}

https://stackoverflow.com/questions/23577787/how-can-i-enumerate-the-list-of-network-devices-or-interfaces-in-c-or-c-in-fre

$ ./i
lo: IP 127.0.0.1, BROADCAST 0.0.0.0
ens33: IP 192.168.80.178, BROADCAST 192.168.80.255
docker0: IP 172.17.0.1, BROADCAST 172.17.255.255

#4 Re: DIY/综合/Arduino/写字机/3D打印机/智能小车/平衡车/四轴飞行/MQTT/物联网 » C 网络编程 » 2023-03-15 10:51:34

或者用另外一个方法:

This is OS specific, there's no unified(or ANSI C) API for this.

Assuming Linux, the best way is to just parse /proc/net/route , look for the entry where Destination is 00000000 , the default gateway is in the Gateway column , where you can read the hex representation of the gateway IP address (in big endian , I believe)

If you want to do this via more specific API calls, you'll have to go through quite some hoops, here's an example program:



https://stackoverflow.com/questions/3288065/getting-gateway-to-use-for-a-given-ip-in-ansi-c


#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>


#define BUFSIZE 8192
char gateway[255];

struct route_info {
    struct in_addr dstAddr;
    struct in_addr srcAddr;
    struct in_addr gateWay;
    char ifName[IF_NAMESIZE];
};

int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId)
{
    struct nlmsghdr *nlHdr;
    int readLen = 0, msgLen = 0;

 do {
    /* Recieve response from the kernel */
        if ((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) {
            perror("SOCK READ: ");
            return -1;
        }

        nlHdr = (struct nlmsghdr *) bufPtr;

    /* Check if the header is valid */
        if ((NLMSG_OK(nlHdr, readLen) == 0)
            || (nlHdr->nlmsg_type == NLMSG_ERROR)) {
            perror("Error in recieved packet");
            return -1;
        }

    /* Check if the its the last message */
        if (nlHdr->nlmsg_type == NLMSG_DONE) {
            break;
        } else {
    /* Else move the pointer to buffer appropriately */
            bufPtr += readLen;
            msgLen += readLen;
        }

    /* Check if its a multi part message */
        if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) {
           /* return if its not */
            break;
        }
    } while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));
    return msgLen;
}
/* For printing the routes. */
void printRoute(struct route_info *rtInfo)
{
    char tempBuf[512];

/* Print Destination address */
    if (rtInfo->dstAddr.s_addr != 0)
        strcpy(tempBuf,  inet_ntoa(rtInfo->dstAddr));
    else
        sprintf(tempBuf, "*.*.*.*\t");
    fprintf(stdout, "%s\t", tempBuf);

/* Print Gateway address */
    if (rtInfo->gateWay.s_addr != 0)
        strcpy(tempBuf, (char *) inet_ntoa(rtInfo->gateWay));
    else
        sprintf(tempBuf, "*.*.*.*\t");
    fprintf(stdout, "%s\t", tempBuf);

    /* Print Interface Name*/
    fprintf(stdout, "%s\t", rtInfo->ifName);

    /* Print Source address */
    if (rtInfo->srcAddr.s_addr != 0)
        strcpy(tempBuf, inet_ntoa(rtInfo->srcAddr));
    else
        sprintf(tempBuf, "*.*.*.*\t");
    fprintf(stdout, "%s\n", tempBuf);
}

void printGateway()
{
    printf("%s\n", gateway);
}
/* For parsing the route info returned */
void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo)
{
    struct rtmsg *rtMsg;
    struct rtattr *rtAttr;
    int rtLen;

    rtMsg = (struct rtmsg *) NLMSG_DATA(nlHdr);

/* If the route is not for AF_INET or does not belong to main routing table
then return. */
    if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
        return;

/* get the rtattr field */
    rtAttr = (struct rtattr *) RTM_RTA(rtMsg);
    rtLen = RTM_PAYLOAD(nlHdr);
    for (; RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) {
        switch (rtAttr->rta_type) {
        case RTA_OIF:
            if_indextoname(*(int *) RTA_DATA(rtAttr), rtInfo->ifName);
            break;
        case RTA_GATEWAY:
            rtInfo->gateWay.s_addr= *(u_int *) RTA_DATA(rtAttr);
            break;
        case RTA_PREFSRC:
            rtInfo->srcAddr.s_addr= *(u_int *) RTA_DATA(rtAttr);
            break;
        case RTA_DST:
            rtInfo->dstAddr .s_addr= *(u_int *) RTA_DATA(rtAttr);
            break;
        }
    }
    //printf("%s\n", inet_ntoa(rtInfo->dstAddr));

    if (rtInfo->dstAddr.s_addr == 0)
        sprintf(gateway, (char *) inet_ntoa(rtInfo->gateWay));
    //printRoute(rtInfo);

    return;
}


int main()
{
    struct nlmsghdr *nlMsg;
    struct rtmsg *rtMsg;
    struct route_info *rtInfo;
    char msgBuf[BUFSIZE];

    int sock, len, msgSeq = 0;

/* Create Socket */
    if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
        perror("Socket Creation: ");

    memset(msgBuf, 0, BUFSIZE);

/* point the header and the msg structure pointers into the buffer */
    nlMsg = (struct nlmsghdr *) msgBuf;
    rtMsg = (struct rtmsg *) NLMSG_DATA(nlMsg);

/* Fill in the nlmsg header*/
    nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));  // Length of message.
    nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .

    nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;    // The message is a request for dump.
    nlMsg->nlmsg_seq = msgSeq++;    // Sequence of the message packet.
    nlMsg->nlmsg_pid = getpid();    // PID of process sending the request.

/* Send the request */
    if (send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) {
        printf("Write To Socket Failed...\n");
        return -1;
    }

/* Read the response */
    if ((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {
        printf("Read From Socket Failed...\n");
    return -1;
    }
/* Parse and print the response */
    rtInfo = (struct route_info *) malloc(sizeof(struct route_info));
//fprintf(stdout, "Destination\tGateway\tInterface\tSource\n");
    for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) {
        memset(rtInfo, 0, sizeof(struct route_info));
        parseRoutes(nlMsg, rtInfo);
    }
    free(rtInfo);
    close(sock);

    printGateway();
    return 0;
}

#5 Re: DIY/综合/Arduino/写字机/3D打印机/智能小车/平衡车/四轴飞行/MQTT/物联网 » C 网络编程 » 2023-03-15 10:48:00

获取网关地址:

$ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.80.2    0.0.0.0         UG    100    0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.80.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33
$ route -n |grep ens33 | grep 'UG[ \t]' | awk '{print $2}'
192.168.80.2

https://stackoverflow.com/questions/3288065/getting-gateway-to-use-for-a-given-ip-in-ansi-c

char* GetGatewayForInterface(const char* interface) 
{
    char* gateway = NULL;

    char cmd [1000] = {0x0};
    sprintf(cmd,"route -n | grep %s  | grep 'UG[ \t]' | awk '{print $2}'", interface);
    FILE* fp = popen(cmd, "r");
    char line[256]={0x0};

    if(fgets(line, sizeof(line), fp) != NULL)
        gateway = string(line);


    pclose(fp);
}

#6 DIY/综合/Arduino/写字机/3D打印机/智能小车/平衡车/四轴飞行/MQTT/物联网 » C 网络编程 » 2023-03-15 10:37:46

uuid
回复: 4

https://stackoverflow.com/questions/4951257/using-c-code-to-get-same-info-as-ifconfig

#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>

void parse_ioctl(const char *ifname)
{
    printf("%s\n", "scarf rosari...");
    int sock;
    struct ifreq ifr;
    struct sockaddr_in *ipaddr;
    char address[INET_ADDRSTRLEN];
    size_t ifnamelen;

    /* copy ifname to ifr object */
    ifnamelen = strlen(ifname);
    if (ifnamelen >= sizeof(ifr.ifr_name)) {
        printf("error :%s\n", ifr.ifr_name);
        return ;
    }
    memcpy(ifr.ifr_name, ifname, ifnamelen);
    ifr.ifr_name[ifnamelen] = '\0';

    /* open socket */
    sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
    if (sock < 0) {
        printf("error :%s\n", "unable to open socket..");
        return;
    }

    /* process mac */
    if (ioctl(sock, SIOCGIFHWADDR, &ifr) != -1) {
        printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
                (unsigned char)ifr.ifr_hwaddr.sa_data[0],
                (unsigned char)ifr.ifr_hwaddr.sa_data[1],
                (unsigned char)ifr.ifr_hwaddr.sa_data[2],
                (unsigned char)ifr.ifr_hwaddr.sa_data[3],
                (unsigned char)ifr.ifr_hwaddr.sa_data[4],
                (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
    }

    /* process mtu */
    if (ioctl(sock, SIOCGIFMTU, &ifr) != -1) {
        printf("MTU: %d\n", ifr.ifr_mtu);
    }

    /* die if cannot get address */
    if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) {
        close(sock);
        return;
    }

    /* process ip */
    ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;
    if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
        printf("Ip address: %s\n", address);
    }

    /* try to get broadcast */
    if (ioctl(sock, SIOCGIFBRDADDR, &ifr) != -1) {
        ipaddr = (struct sockaddr_in *)&ifr.ifr_broadaddr;
        if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
            printf("Broadcast: %s\n", address);
        }
    }

    /* try to get mask */
    if (ioctl(sock, SIOCGIFNETMASK, &ifr) != -1) {
        ipaddr = (struct sockaddr_in *)&ifr.ifr_netmask;
        if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
            printf("Netmask: %s\n", address);
        }
    }

    close(sock);
}

int main()
{
        parse_ioctl("eth0");
}
$ ./getip2
scarf rosari...
Mac address: 00:0c:29:0e:eb:92
MTU: 1500
Ip address: 192.168.80.178
Broadcast: 192.168.80.255
Netmask: 255.255.255.0

#7 Re: 全志 SOC » T113-S3 一个很奇怪的USB问题 » 2023-03-14 10:05:08

大概率还是电源问题,可以试一试4G模块单独供电先试一试。

#9 Re: 全志 SOC » 小菜鸟又有新问题了, tinyalsa如何编译成arm-linux 静态链接版本 » 2022-12-06 13:41:08

yixiuge 说:

@yixiuge
./utils/tinyplay /dev/urandom -r 6000 -i raw
./utils/tinyplay /dev/urandom -r 12000 -i raw
./utils/tinyplay /dev/urandom -r 24000 -i raw
./utils/tinyplay /dev/urandom -r 48000 -i raw

ubuntu 18.04 这几个测试OK,其他的采样率都不行。

$ tinyplay /dev/urandom -r 44100
failed to open for pcm 0,0


好奇试了一下,果然是 。。。

#13 Re: 全志 SOC » uImage相比zImage,有那些好处? » 2022-06-18 08:48:40

就是为了解决 "starting kernel ..." 然后就没有然后的问题,提前让你知道zImage是不是完整的


解决 V3s / F1C100s  Linux 显示 starting kernel ...  就没有然后的问题 (earlyprintk)
https://whycan.com/t_2402.html

#14 Re: 全志 SOC » 写一个非常简单的 V3s@linux4.13-y 中断驱动 » 2022-04-01 15:38:20

把楼主的 hello.c 和 Makefile 复制后,编译:

ARCH=arm64 CROSS_COMPILE=/opt/a100/longan/out/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- make -C /opt/a100/longan/kernel/linux-4.9/ M=${PWD} modules

A133 的板子, 一块能中断, 一块不能中断,一头雾水。

#15 Re: 全志 SOC » 关于驱动ST7701S液晶屏初始化的疑问(荔枝派nano) » 2022-03-12 23:07:37

ne_demon 说:
memory 说:

用 aodzip 那个sdk ?

用的荔枝派官方的主线linux

具体一点

都不知道你用什么芯片,哪个sdk版本。

#17 Re: 司徒开源 » 研究FC3000掌機的開源可行性 » 2022-03-07 13:36:41

请问司徒 f1c 驱动 i80 mcu屏用的是 gpio 模式吗? 还是别的方式?

#18 Re: 全志 SOC » 全志 D1 SDK 固打包件文件结构分析 » 2021-12-28 20:04:47

boot.img:

mkbootimg --kernel  Image  --ramdisk  ramdisk.img --board  d1-nezha_min --base  0x40200000 --kernel_offset  0x0 --ramdisk_offset  0x01000000 -o  boot.img

#19 Re: 全志 SOC » 全志 D1 SDK 固打包件文件结构分析 » 2021-12-28 19:55:39

boot_package.fex 包含文件:

① fw_jump.bin 
② u-boot-sun20iw1p1.bin
③ board.dtb

boot_package.fex 使用这个命令生成:

./dragonsecboot  -pack boot_package.cfg

boot_package.cfg 内容:

package]
;item=Item_TOC_name,         Item_filename,
;item=scp,                    scp.fex
item=opensbi,                 fw_jump.bin
item=u-boot,                u-boot-sun20iw1p1.bin
item=dtb,                    board.dtb
;item=logo,                   bootlogo.bmp.lzma
;item=shutdowncharge,         bempty.bmp.lzma
;item=androidcharge,          battery_charge.bmp.lzma

#20 全志 SOC » 全志 D1 SDK 固打包件文件结构分析 » 2021-12-28 19:55:29

uuid
回复: 8

D1 固件文件解构:

① boot0_sdcard.fex

② boot_package.fex

③ env.fex

④ env.fex

⑤ boot.vfat

⑥ rootfs

#23 Re: 好钜润半导体(TIKY) » 好钜润3.5寸屏RGB888模式,无法点亮 » 2021-10-11 13:29:16

@wuyu
嗯,你上面买一块能点亮的板子是对的,用逻辑分析仪把录到的时序用单片机回放出来就OK了。

#25 Re: 全志 SOC » 开源自己的Openwrt衍生版 HandsomeMod 支持f1c100s/f1c200s v3s » 2021-10-06 10:00:22

搭车请教楼主一个问题,全志的sdk tina 用的是 openwrt 14.07,请问这个版本怎么添加 Qt 支持?

#26 全志 SOC » 打包全志A33 SDK 出现No such file or directory 的解决方案 » 2021-09-14 20:03:00

uuid
回复: 0
$ ./build.sh pack
INFO: packing firmware ...
copying tools file
copying configs file
copying boot resource
copying boot file
support dragonboard test emmc when boot from card0
[mmc2_para]-sdc_used: 0 -> 1
./pack: line 263: /opt/a33/a33_linux_sdk/dragonboard/tools/pack/pctools/linux/fsbuild200/fsbuild: No such file or directory
packing for dragonboard
./pack: line 323: /opt/a33/a33_linux_sdk/dragonboard/tools/pack/pctools/linux/eDragonEx/dragon: No such file or directory
pack finish

解决方案:
sudo apt-get install libc6:i386 libgcc1:i386 libstdc++6:i386 -y

原因:
dragon是32位linux的可执行文件,因为我的主机是64bit,所以要安装兼容库。

#29 技术人生/软件使用技巧/破解经验/技术吐槽/灌水 » 凌晨一点中了lockbit勒索病毒,黑客还在我电脑里面拉了一坨翔,大家注意资料备份。 » 2021-09-14 12:28:33

uuid
回复: 9

分析中毒可能的原因:

windows开了frp, 并且开放了vncserver / rdp 端口,弱密码。

虽然windows被锁定,但是administrator的密码是另外一个正在登录着用户的用户名。

幸运的是,虚拟机在另外一个用户,密码不同,所以黑客没有进去,这个虚拟机现在还能备份资料到Windows,等全部备份完成才敢重新启动虚拟机。

#34 Re: 全志 SOC » 全志F25有相关的SDK或主线LINUX吗?手头有一批F25主板,谁有的话可以拿板子换 » 2021-08-31 12:28:30

saub 说:

全志F25有相关的SDK或主线LINUX吗?手头有一批F25主板,谁有的话可以拿板子换

https://www.allwinnertech.com/index.php?c=product&a=index&id=31

没见过这玩意。

#35 Re: 全志 SOC » 我用buildroot产生的rootfs,每次启动都要登录,有什么办法可以去掉这个登录吗? » 2021-08-31 10:59:51

晕哥 说:

找到 /etc/inittab 文件的

console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL

修改为:

console::respawn:-/bin/sh

重启后就没有恼人的 login 提示了.

确实可以了,请问这是什么原理?

#36 全志 SOC » udev 使用方法 (转载) » 2021-08-31 10:19:27

uuid
回复: 0

转载地址: https://blog.csdn.net/qigaohua/article/details/102849031

最近有在研究SD卡设备节点自动创建及挂载,发现TI的达芬奇平台使用的是udev而非mdev,所以花了点时间看了看udev,查到了《udev轻松上路》这篇文章,看了下《Writing udev rules》,那篇文章写的不错,建议有需要的朋友一定要好好看看,另外,在网上有篇关于SD卡和U盘自动创建节点自动挂载的文章,分别通过udev和mdev实现,也可以作为参考,真正理解还需要看看老外的文章,理解下里面的udev书写规则,真正做到标本兼治!

通过上述文章,加上自己的理解,有了这篇文章!

第一、什么是udev?

这篇文章UDEV Primer给我们娓娓道来,花点时间预习一下是值得的。当然,不知道udev是什么也没关系,
把它当个助记符好了,有了下面的上路指南,可以节省很多时间。我们只需要树立一个信念:udev很简单!
嵌入式的udev应用尤其简单。

第二、为什么udev要取代devfs?

这是生产关系适应生产力的需要,udev好,devfs坏,用好的不用坏的。

udev是硬件平台无关的,属于user space的进程,它脱离驱动层的关联而建立在操作系统之上,基于这种设
计实现,我们可以随时修改及删除/dev下的设备文件名称和指向,随心所欲地按照我们的愿望安排和管理设
备文件系统,而完成如此灵活的功能只需要简单地修改udev的配置文件即可,无需重新启动操作系统。udev
已经使得我们对设备的管理如探囊取物般轻松自如。

第三、如何得到udev?

udev的主页在这里:http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html
我们按照下面的步骤来生成udev的工具程序,以arm-linux为例:

1、wget http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/udev-100.tar.bz2
2、tar xjf udev-100.tar.bz2
3、cd udev-100 编辑Makefile,查找CROSS_COMPILE,修改CROSS_COMPILE ?= arm-linux-
4、make

没有什么意外的话当前目录下生成udev,udevcontrol,udevd,udevinfo,udevmonitor,udevsettle,udevstart,
udevtest,udevtrigger九个工具程序,在嵌入式系统里,我们只需要udevd和udevstart就能使udev工作得很好,
其他工具则帮助我们完成udev的信息察看、事件捕捉或者更高级的操作。

另外一个方法是直接使用debian提供的已编译好的二进制包,美中不足的是版本老了一些。

1、wget http://ftp.us.debian.org/debian/pool/main/u/udev/udev_0.056-3_arm.deb
2、ar -xf udev_0.056-3_arm.deb
3、tar xzf data.tar.gz

在sbin目录里就有我们需要的udevd和udevstart工具程序。

建议大家采用第一种方式生成的udevd和udevstart。为什么要用最新udev呢?新的强,旧的弱,用强的不用弱的。

第四、如何配置udev?

首先,udev需要内核sysfs和tmpfs的支持,sysfs为udev提供设备入口和uevent通道,tmpfs为udev设备文件提
供存放空间,也就是说,在上电之前系统上是没有足够的设备文件可用的,我们需要一些技巧让kernel先引导
起来。

由于在kernel启动未完成以前我们的设备文件不可用,如果使用mtd设备作为rootfs的挂载点,这个时候/dev/mtdblock
是不存在的,我们无法让kernel找到rootfs,kernel只好停在那里惊慌。
这个问题我们可以通过给kernel传递设备号的方式来解决,在linux系统中,mtdblock的主设备号是31,part号
从0开始,那么以前的/dev/mtdblock/3就等同于31:03,以次类推,所以我们只需要修改bootloader传给kernel
的cmd line参数,使root=31:03,就可以让kernel在udevd未起来之前成功的找到rootfs。
O.K.下一个问题。

其次,需要做的工作就是重新生成rootfs,把udevd和udevstart复制到/sbin目录。然后我们需要在/etc/下为udev
建立设备规则,这可以说是udev最为复杂的一步。这篇文章提供了最完整的指导:Writing udev rules (http://reactivated.net/writing_udev_rules.html)
文中描述的复杂规则我们可以暂时不用去理会,上路指南将带领我们轻松穿过这片迷雾。这里提供一个由简入
繁的方法,对于嵌入式系统,这样做可以一劳永逸。

1、在前面用到的udev-100目录里,有一个etc目录,里面放着的udev目录包含了udev设备规则的详细样例文
本。为了简单而又简洁,我们只需要用到etc/udev/udev.conf这个文件,在我们的rootfs/etc下建立一个udev目
录,把它复制过去,这个文件很简单,除了注释只有一行,是用来配置日志信息的,嵌入式系统也许用不上
日志,但是udevd需要检查这个文件。

2、在rootfs/etc/udev下建立一个rules.d目录,生成一个空的配置文件touch etc/udev/rules.d/udev.conf。然后
我们来编辑这个文件并向它写入以下配置项:

###############################################
# vc devices
KERNEL=="tty[0-9]*", NAME="vc/%n"

# block devices
KERNEL=="loop[0-9]*", NAME="loop/%n"

# mtd devices
KERNEL=="mtd[0-9]*", NAME="mtd/%n"
KERNEL=="mtdblock*", NAME="mtdblock/%n"

# input devices
KERNEL=="mice" NAME="input/%k"
KERNEL=="mouse[0-9]*", NAME="input/%k"
KERNEL=="ts[0-9]*", NAME="input/%k"
KERNEL=="event[0-9]*", NAME="input/%k"

# misc devices
KERNEL=="apm_bios", NAME="misc/%k"
KERNEL=="rtc", NAME="misc/%k"
################################################

保存它,我们的设备文件系统基本上就可以了,udevd和udevstart会自动分析这个文件。

这里重点说下%n,先来看2个例子:

# cat /etc/udev/rules.d/honeywell.rules
#Honeywell
#SD card
#KERNEL=="mmcblk[0-9]p*", NAME="SD/%n", SYMLINK+="SdPart%n", RUN+="/sbin/SdCard", OPTIONS+="last_rule"
KERNEL=="mmcblk*", NAME="SD/%n",SYMLINK+="SdPart%n",RUN+="/sbin/SdCard"
#

插入SD卡:

# ls /dev/SD/ -l
brw-rw----    1 root     root     254,   0 Jan  1 00:41 0
brw-rw----    1 root     root     254,   1 Jan  1 00:41 1
# ls /dev/SdPart* -l
lrwxrwxrwx    1 root     root            4 Jan  1 00:41 /dev/SdPart0 -> SD/0
lrwxrwxrwx    1 root     root            4 Jan  1 00:41 /dev/SdPart1 -> SD/1
#
#

修改规则后:

# cat /etc/udev/rules.d/honeywell.rules
#Honeywell
#SD card
#KERNEL=="mmcblk[0-9]p*", NAME="SD/%n", SYMLINK+="SdPart%n", RUN+="/sbin/SdCard", OPTIONS+="last_rule"
KERNEL=="mmcblk0p*", NAME="SD/%n",SYMLINK+="SdPart%n",RUN+="/sbin/SdCard"
#

插入SD卡(需要先umount)

#
# ls -l /dev/SD/
brw-rw----    1 root     root     254,   1 Jan  1 00:49 1
#
# ls -l /dev/SdPart*
lrwxrwxrwx    1 root     root            4 Jan  1 00:49 /dev/SdPart1 -> SD/1
#

修改部分内容后如下:

# cat /etc/udev/rules.d/honeywell.rules
#Honeywell
#SD card
#KERNEL=="mmcblk[0-9]p*", NAME="SD/%n", SYMLINK+="SdPart%n", RUN+="/sbin/SdCard", OPTIONS+="last_rule"
KERNEL=="mmcblk?", NAME="SD/%n",SYMLINK+="SdPart%n",RUN+="/sbin/SdCard"
#

插入SD卡:

#
# ls -l /dev/SD/
brw-rw----    1 root     root     254,   0 Jan  1 00:54 0
# ls -l /dev/Sd*
lrwxrwxrwx    1 root     root            4 Jan  1 00:54 /dev/SdPart0 -> SD/0
#

结论:

%n是KERNEL中的数字号码,

    在 KERNEL=="mmcblk*"中,KERNEL分别匹配mmcblk0(SD卡)和mmcblk0p1(SD卡1分区),所以%n分别对应数字0 1,也就创建了/dev/SdPart0 /dev/SdPart1两个软链接,
    当改为KERNEL=="mmcblk0p*"时,KERNEL只能匹配到mmcblk0p1,所以只会创建/dev/SdPart1软连接。
    当改为KERNEL=="mmcblk?"时,KERNEL只匹配一次,优先匹配为到mmcblk0,所以只会创建/dev/SdPart0软连接


3、为了使udevd在kernel起来后能够自动运行,我们在rootfs/etc/init.d/rcS中增加以下几行:

##################################
/bin/mount -t tmpfs tmpfs /dev

echo "Starting udevd..."
/sbin/udevd --daemon
/sbin/udevstart
##################################

4、重新生成rootfs,烧写到flash指定的rootfs part中。

5、如果需要动态改变设备规则,可以把etc/udev放到jffs或yaffs part,以备修改,根据需求而定,可以随时扩
充udev.conf中的配置项。

6、我们知道,用户空间的程序与设备通信的方法,主要有以下几种方式,
  1. 通过ioperm获取操作IO端口的权限,然后用inb/inw/ inl/ outb/outw/outl等函数,避开设备驱动程序,直接去操作IO端口。(没有用过)
  2. 用ioctl函数去操作/dev目录下对应的设备,这是设备驱动程序提供的接口。像键盘、鼠标和触摸屏等输入设备一般都是这样做的。
  3. 用write/read/mmap去操作/dev目录下对应的设备,这也是设备驱动程序提供的接口。像framebuffer等都是这样做的。
 
  上面的方法在大多数情况下,都可以正常工作,但是对于热插拨(hotplug)的设备,比如像U盘,就有点困难了,因为你不知道:什么时候设备插上了,什么时候设备拔掉了。这就是所谓的hotplug问题了。
 
  处理hotplug传统的方法是,在内核中执行一个称为hotplug的程序,相关参数通过环境变量传递过来,再由hotplug通知其它关注 hotplug事件的应用程序。这样做不但效率低下,而且感觉也不那么优雅。新的方法是采用NETLINK实现的,这是一种特殊类型的socket,专门用于内核空间与用户空间的异步通信。下面的这个简单的例子,可以监听来自内核hotplug的事件。

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <ctype.h>  
#include <sys/un.h>  
#include <sys/ioctl.h>  
#include <sys/socket.h>  
#include <linux/types.h>  
#include <linux/netlink.h>  
#include <errno.h>  
#include <unistd.h>  
#include <arpa/inet.h>  
#include <netinet/in.h>  

#define UEVENT_BUFFER_SIZE 2048  

static int init_hotplug_sock()  
{  
  const int buffersize = 1024;  
  int ret;  

  struct sockaddr_nl snl;  
  bzero(&snl, sizeof(struct sockaddr_nl));  
  snl.nl_family = AF_NETLINK;  
  snl.nl_pid = getpid();  
  snl.nl_groups = 1;  

  int s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);  
  if (s == -1)   
  {  
  perror("socket");  
  return -1;  
  }  
  setsockopt(s, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));  

  ret = bind(s, (struct sockaddr *)&snl, sizeof(struct sockaddr_nl));  
  if (ret < 0)   
  {  
  perror("bind");  
  close(s);  
  return -1;  
  }  

  return s;  
}  

int main(int argc, char* argv[])  
{  
  int hotplug_sock = init_hotplug_sock();  

  while(1)  
  {  
  /* Netlink message buffer */  
  char buf[UEVENT_BUFFER_SIZE * 2] = {0};  
  recv(hotplug_sock, &buf, sizeof(buf), 0);  
printf("%s\n", buf);  

  /* USB 设备的插拔会出现字符信息,通过比较不同的信息确定特定设备的插拔,在这添加比较代码 */

  }
  return 0;  
}

udev的主体部分在udevd.c文件中,它主要监控来自4个文件描述符的事件/消息,并做出处理:
  1. 来自客户端的控制消息。这通常由udevcontrol命令通过地址为/org/kernel/udev/udevd的本地socket,向udevd发送的控制消息。其中消息类型有:
  l UDEVD_CTRL_STOP_EXEC_QUEUE 停止处理消息队列。
  l UDEVD_CTRL_START_EXEC_QUEUE 开始处理消息队列。
  l UDEVD_CTRL_SET_LOG_LEVEL 设置LOG的级别。
  l UDEVD_CTRL_SET_MAX_CHILDS 设置最大子进程数限制。好像没有用。
  l UDEVD_CTRL_SET_MAX_CHILDS_RUNNING 设置最大运行子进程数限制(遍历proc目录下所有进程,根据session的值判断)。
  l UDEVD_CTRL_RELOAD_RULES 重新加载配置文件。
  2. 来自内核的hotplug事件。如果有事件来源于hotplug,它读取该事件,创建一个udevd_uevent_msg对象,记录当前的消息序列号,设置消息的状态为EVENT_QUEUED,然后并放入running_list和exec_list两个队列中,稍后再进行处理。
  3. 来自signal handler中的事件。signal handler是异步执行的,即使有signal产生,主进程的select并不会唤醒,为了唤醒主进程的select,它建立了一个管道,在 signal handler中,向该管道写入长度为1个子节的数据,这样就可以唤醒主进程的select了。
  4. 来自配置文件变化的事件。udev通过文件系统inotify功能,监控其配置文件目录/etc/udev/rules.d,一旦该目录中文件有变化,它就重新加载配置文件。
 
  其中最主要的事件,当然是来自内核的hotplug事件,如何处理这些事件是udev的关键。udev本身并不知道如何处理这些事件,也没有必要知道,因为它只实现机制,而不实现策略。事件的处理是由配置文件决定的,这些配置文件即所谓的rule。
 
  关于rule的编写方法可以参考《writing_udev_rules》,udev_rules.c实现了对规则的解析。
 
  在规则中,可以让外部应用程序处理某个事件,这有两种方式,一种是直接执行命令,通常是让modprobe去加载驱动程序,或者让mount去加载分区。另外一种是通过本地socket发送消息给某个应用程序。
 
  在udevd.c:udev_event_process函数中,我们可以看到,如果RUN参数以”socket:”开头则认为是发到socket,否则认为是执行指定的程序。
 
  下面的规则是执行指定程序:
  60-pcmcia.rules: RUN+="/sbin/modprobe pcmcia"
 
  下面的规则是通过socket发送消息:
  90-hal.rules:RUN+="socket:/org/freedesktop/hal/udev_event"



mission completed!

-----------------------------------------

在2.6内核里面,如果配置了sysfs的话,kernel启动的时候会自动在sysfs空间查找root设备。所以,型如root=/dev/mtdblock3等的参数还是可以工作的。至少在我这里可以。

-----------------------------------------

是这样的,谢谢指正!

更正如下:
========================
由于在kernel启动未完成以前我们的设备文件不可用,如果使用mtd设备作为rootfs的挂载点,这个时候/dev/mtdblock 这个设备目录是不存在的,我们无法让kernel通过/dev/mtdblock/X这样的设备找到rootfs,kernel只好停在那里惊慌。
这个问题我们可以通过给kernel传递设备号的方式来解决,在linux系统中,mtdblock的主设备号是31,part号 从0开始,那么以前的/dev/mtdblock/3就等同于31:03,以次类推,所以我们只需要修改bootloader传给kernel 的cmd line参数,使root=31:03,就可以让kernel在udevd未起来之前成功的找到rootfs。

另外一种方法就是给kernel传递未经归类的设备文件名,在udev未创建之前,所有的设备实际上已经通过sysfs 建立,mtdblockX的位置相对于/sys/block/mtdblockX/dev,这个文件里存放着mtdblockX的设备号,形式与上 一种方式相同。这时由于没有相应的udev规则,所有的设备都被隐含地映射到/dev目录下,mtdblockX对应于 /dev/mtdbockX,这样我们给kernel传递root=/dev/mtdblock3,kernel发现/dev没有被建立,就自动从映射表里 查找对应关系,最后取出/sys/block/mtdblockX/dev里的设备号,完成rootfs的挂载。
========================

-----------------------------------------

>2、在rootfs/etc/udev下建立一个rules.d目录,生成一个空的配置文件touch etc/udev/rules.d/udev.conf。 这里是不是有些问题,我本机上的udev.conf文件是在/etc/udev/下的。
-----------------------------------------

在udev_version.h中有以下两个定义:
#define UDEV_CONFIG_FILE "/etc/udev/udev.conf"
#define UDEV_RULES_FILE "/etc/udev/rules.d"

我想之所以采用rules.d的目录形式,其目的和rcX.d相同,可以在规则十分复杂的情况下用数字链接的方式控制
启动顺序。由于版本的不断升级,代码以及结构也越来越漂亮。

我们按照这种默认的方式来编写和存放规则文件,不失为一个好习惯。

-----------------------------------------

我的/etc/udev/下有rules.d目录和udev.conf文件
我的意思是udev.conf文件是否应该在/etc/udev目录而非/etc/udev/rules.d目录下

-----------------------------------------

是这样的,谢谢指正!

更正如下:
========================
2、在rootfs/etc/udev下建立一个rules.d目录,生成一个空的配置文件touch etc/udev/rules.d/udev.rules。
========================

兄弟确实是火眼金睛啊,这里有个笔误。

-----------------------------------------

pc的应用相对复杂些。

通过查看pc上的脚本/etc/init.d/udev我们发现:

udevtrigger同样可以完成udevstart所做的事情,而且它能够兼容以前MAKEDEV创建/dev的方式,配合MAKEDEV
把漏掉的设备自动补上。

udevsettle用来检查/dev是不是已经按照我们的规则在指定时间内创建完成,不管结果如何,只是向系统写入
一个报告,并不能够解决所遇到的问题。

udevstart是强制性的,udevtrigger则先做判断。

嵌入式系统上远没有这么复杂,所以我推荐在用udevstart来一次完成/dev的创建工作,因为现在的udevtrigger
还存在一些问题,处理uevent有时会重复创建同一个设备,创建失败的提示看起来很不美观。

-----------------------------------------

我看到这样的一段说明:
Every time the kernel notices an update in the device structure, it calls the /sbin/hotplug program. Hotplug runs the applications linked in the /etc/hotplug.d/default directory where you will also find a symlink to the udev application. Hotplug directs the information given by the kernel to the udev application which performs the necessary actions on the /dev structure (creating or deleting device files).

Q1: 在嵌入式系统中只需要udevd和udevstart就够了吗??? 不需要udev吗?

Q2: 不需要在/etc/hotplug.d/default 目录下建立到udev的符号链接吗? 如果不建立,hotplug怎样通知udev了????

-----------------------------------------

这段说明已经是老皇历了。
在古代的时候是需要hotplug的,现在这种framework已经被抛弃。
取而代之的是udevd通过netlink接口接收内核发来的消息。

-----------------------------------------

【相关资源】

Udev最新source code源码下载:

http://www.us.kernel.org/pub/linux/utils/kernel/hotplug/

【相关文章】

1.Udev
2.The README file in the udev source tree.
3.A OLS 2003 paper about how udev was originally designed, and why it was created.
4.The OLS 2003 presentation that went along with the paper.
5.An article about udev and how it works was published in Linux Journal in 2004.
6.Writing udev rules
7.A general udev primer
8.The last word on how udev and devfs compare.

#37 Re: 全志 SOC » 哪吒D1使用gstreamer硬解码 » 2021-08-26 09:34:07

强大,那投屏也可以了吧?

#38 Re: 全志 SOC » 点屏强芯全志D1s可以申请样片了,本站网友开源原理图与PCB送两片D1s(不能与其他网友作品雷同) » 2021-08-23 12:23:27

jimmy_xt 说:

@拉轰的脚踏车
可惜还是不支持eDP

好像只看到 全志A80 支持 eDP, 其它芯片还没注意到呢。

#39 Re: 全志 SOC » [V3X][Mystery]项目开发进度汇报 » 2021-08-18 20:23:40

xfdr0805 说:

这颗芯片有I2S接口吗?楼主能上传一份手册吗?

遗憾,没有I2S。

V3x 手册: V3x_Datasheet_V1.0.pdf

dxp原理图封装下载: whycan_v3x_schlib.7z

#40 Re: 全志 SOC » LVDS电路硬件设计 » 2021-07-31 20:30:09

这种 15寸LVDS液晶的驱动板有没有朋友用过?
https://whycan.com/t_5120.html#p52049



这种LVDS驱动板, 感觉也没特殊处理。

#41 Re: 全志 SOC » 求助,F1c100s 启动正常,但是一会儿就报错重启失败!? » 2021-07-14 22:38:54

lovexulu 说:

90% 确认是 SD卡时钟线走过晶振引脚下方! 严重设计失误。。。

这么说, 好像是哦。

#42 Re: 全志 SOC » tiny200 tina 接tv 摄像头跑 mjpg-streamer 挂了 » 2021-04-14 14:09:31

[ 1084.260061] tvd_open:
[ 1084.263619] __tvd_clk_init: dev->interface = 0, dev->system = 0
[ 1084.270367] div = 11
[ 1084.272809] __tvd_clk_init: parent = 297000000, clk = 27000000
[ 1084.290296] vidioc_s_fmt_vid_cap:
[ 1084.294008] interface=0
[ 1084.296718] system=0
[ 1084.299136] format=1
[ 1084.301706] width=720
[ 1084.304229] height=480
[ 1084.333673] __tvd_clk_init: dev->interface = 0, dev->system = 0
[ 1084.340404] div = 11
[ 1084.342844] __tvd_clk_init: parent = 297000000, clk = 27000000
[ 1084.352737] vidioc_reqbufs:
[ 1084.356041] queue_setup, buffer count=4, size=518400
[ 1084.375106] tvd_mmap: mmap called, vma=0xc0f7f528
[ 1084.381332] tvd_mmap: vma start=0xb6e84000, size=520192, ret=0
[ 1084.387949] tvd_mmap: mmap called, vma=0xc0f7f5d8
[ 1084.394380] tvd_mmap: vma start=0xb6e05000, size=520192, ret=0
[ 1084.401909] tvd_mmap: mmap called, vma=0xc1b01420
[ 1084.407280] tvd_mmap: vma start=0xb6d86000, size=520192, ret=0
[ 1084.415035] tvd_mmap: mmap called, vma=0xc1b01738
[ 1084.421243] tvd_mmap: vma start=0xb6d07000, size=520192, ret=0
[ 1084.429446] vidioc_enum_fmt_vid_cap:
[ 1084.434647] vidioc_enum_fmt_vid_cap:
[ 1084.440062] vidioc_enum_fmt_vid_cap:
[ 1084.445996] vidioc_enum_fmt_vid_cap:
[ 1084.451005] vidioc_enum_fmt_vid_cap:
[ 1084.455042] vidioc_enum_fmt_vid_cap:
[ 1084.459030] vidioc_enum_fmt_vid_cap:
[ 1084.464408] vidioc_enum_fmt_vid_cap:
[ 1084.468448] vidioc_enum_fmt_vid_cap:
[ 1084.473665] vidioc_enum_fmt_vid_cap:
[ 1084.477702] vidioc_enum_fmt_vid_cap:
[ 1084.482886] vidioc_enum_fmt_vid_cap:
[ 1084.486926] vidioc_enum_fmt_vid_cap:
[ 1084.492205] vidioc_enum_fmt_vid_cap:
[ 1084.496239] vidioc_enum_fmt_vid_cap:
[ 1084.515310] vidioc_streamon: dev->id=[0]
[ 1084.519699] start_streaming:
[ 1084.523140] [vidioc_streamon]: [934]
[ 1084.527107] [vidioc_streamon]: [936]
[ 1116.546702] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb8c00
[ 1116.588212] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9800
[ 1116.637450] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9400
[ 1116.678828] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9000
[ 1116.686649] No more free frame on next time
[ 1116.715894] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb8c00
[ 1116.723744] No more free frame on next time
[ 1116.758462] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9800
[ 1116.766310] tvd_isr: No more free frame
[ 1116.801006] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9400
[ 1116.808852] No more free frame on next time
[ 1116.843570] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9000
[ 1116.851417] No more free frame on next time
[ 1116.886130] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb8c00
[ 1116.928689] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9800
[ 1118.503420] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9400
[ 1130.548257] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9800
[ 1130.596810] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9400
[ 1130.638469] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9000
[ 1130.675568] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb8c00
[ 1130.718139] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9800
[ 1130.725988] No more free frame on next time
[ 1130.760691] tvd_isr: Nobody is waiting on this video buffer,buf = 0xc0fb9400
[ 1130.768540] tvd_isr: No more free frame
[ 1130.803294] Unable to handle kernel paging request at virtual address 4e98af9b
[ 1130.811333] pgd = c0fb4000
[ 1130.814338] [4e98af9b] *pgd=00000000
[ 1130.818319] Internal error: Oops: 1 [#1] ARM
[ 1130.823054] Modules linked in: tvin videobuf2_dma_contig videobuf2_memops videobuf2_core icn85xx_ts 8723bs snd_pcm_oss snd_mixer_oss snd_seq_device
[ 1130.837778] CPU: 0 PID: 255 Comm: mjpg_streamer Not tainted 3.10.65 #83
[ 1130.845121] task: c1832dc0 ti: c0fb0000 task.ti: c0fb0000
[ 1130.851155] PC is at tvd_isr+0x60/0x1a4 [tvin]
[ 1130.856107] LR is at handle_irq_event_percpu+0x38/0x1a4
[ 1130.861910] pc : [<bf1f559c>]    lr : [<c005f158>]    psr: 20000093
[ 1130.861910] sp : c0fb1ed8  ip : c0fb1ef8  fp : c0fb1ef4
[ 1130.874638] r10: c0593641  r9 : 80808080  r8 : 00000000
[ 1130.880432] r7 : c0e9d9d8  r6 : c0e9dc7c  r5 : c0e9dc7c  r4 : c0e9dc00
[ 1130.887669] r3 : 4e98aed3  r2 : 4e98af9b  r1 : 00000001  r0 : 00000070
[ 1130.894910] Flags: nzCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
[ 1130.902918] Control: 0005317f  Table: 80fb4000  DAC: 00000015
[ 1130.909284]
[ 1130.909284] LR: 0xc005f0d8:
[ 1130.914018] f0d8  c042dfe8 c042dff2 c042dffc c042e008 c042e014 c042e022 c042e02f c042e03c
[ 1130.923128] f0f8  c042e04c c042e058 c042e065 c04bb880 c0593820 e1a0c00d e92dd800 e24cb004
[ 1130.932237] f118  e3a00000 e89da800 e1a0c00d e92ddff0 e24cb004 e24dd00c e3a08000 e1a05000
[ 1130.941345] f138  e1a04001 e1a07008 e5906000 e59fa164 e5943000 e5941004 e1a00006 e12fff33
[ 1130.950455] f158  e1a09000 e10f3000 e3130080 1a00000e e5da3000 e3530000 1a000008 e5943000
[ 1130.959564] f178  e59f2134 e58d3000 e3a01092 e1a03006 e59f0128 ebfef219 e3a03001 e5ca3000
[ 1130.968670] f198  e10f3000 e3833080 e121f003 e3590001 0a00003d e3590002 1a00000f e5943010
[ 1130.977781] f1b8  e3530000 1a00001e e10f2000 e3823080 e121f003 e5943020 e3831002 e5841020
[ 1130.986895]
[ 1130.986895] SP: 0xc0fb1e58:
[ 1130.991629] 1e58  c04c043c 0000006b c0fb1e7c c0fb1e70 c00617e4 c0061790 bf1f559c 20000093
[ 1131.000738] 1e78  ffffffff c0fb1ec4 c0fb1ef4 c0fb1e90 c000f4b8 c000a1a0 00000070 00000001
[ 1131.009847] 1e98  4e98af9b 4e98aed3 c0e9dc00 c0e9dc7c c0e9dc7c c0e9d9d8 00000000 80808080
[ 1131.018957] 1eb8  c0593641 c0fb1ef4 c0fb1ef8 c0fb1ed8 c005f158 bf1f559c 20000093 ffffffff
[ 1131.028067] 1ed8  c0fdf040 c04c06a8 00000070 00000000 c0fb1f2c c0fb1ef8 c005f158 bf1f554c
[ 1131.037174] 1ef8  c1832df0 4774463a c0fb1f34 c04c06a8 00000070 00000000 80808080 80808080
[ 1131.046283] 1f18  80808080 80808080 c0fb1f44 c0fb1f30 c005f2f4 c005f130 c04c06a8 00000070
[ 1131.055393] 1f38  c0fb1f5c c0fb1f48 c00618bc c005f2d4 00000070 00000070 c0fb1f74 c0fb1f60
[ 1131.064501]
[ 1131.064501] IP: 0xc0fb1e78:
[ 1131.069234] 1e78  ffffffff c0fb1ec4 c0fb1ef4 c0fb1e90 c000f4b8 c000a1a0 00000070 00000001
[ 1131.078344] 1e98  4e98af9b 4e98aed3 c0e9dc00 c0e9dc7c c0e9dc7c c0e9d9d8 00000000 80808080
[ 1131.087451] 1eb8  c0593641 c0fb1ef4 c0fb1ef8 c0fb1ed8 c005f158 bf1f559c 20000093 ffffffff
[ 1131.096561] 1ed8  c0fdf040 c04c06a8 00000070 00000000 c0fb1f2c c0fb1ef8 c005f158 bf1f554c
[ 1131.105670] 1ef8  c1832df0 4774463a c0fb1f34 c04c06a8 00000070 00000000 80808080 80808080
[ 1131.114780] 1f18  80808080 80808080 c0fb1f44 c0fb1f30 c005f2f4 c005f130 c04c06a8 00000070
[ 1131.123888] 1f38  c0fb1f5c c0fb1f48 c00618bc c005f2d4 00000070 00000070 c0fb1f74 c0fb1f60
[ 1131.132999] 1f58  c005eb98 c00617f8 c04c7960 00000070 c0fb1f94 c0fb1f78 c00107d8 c005eb80
[ 1131.142111]
[ 1131.142111] FP: 0xc0fb1e74:
[ 1131.146845] 1e74  20000093 ffffffff c0fb1ec4 c0fb1ef4 c0fb1e90 c000f4b8 c000a1a0 00000070
[ 1131.155956] 1e94  00000001 4e98af9b 4e98aed3 c0e9dc00 c0e9dc7c c0e9dc7c c0e9d9d8 00000000
[ 1131.165067] 1eb4  80808080 c0593641 c0fb1ef4 c0fb1ef8 c0fb1ed8 c005f158 bf1f559c 20000093
[ 1131.174177] 1ed4  ffffffff c0fdf040 c04c06a8 00000070 00000000 c0fb1f2c c0fb1ef8 c005f158
[ 1131.183284] 1ef4  bf1f554c c1832df0 4774463a c0fb1f34 c04c06a8 00000070 00000000 80808080
[ 1131.192391] 1f14  80808080 80808080 80808080 c0fb1f44 c0fb1f30 c005f2f4 c005f130 c04c06a8
[ 1131.201500] 1f34  00000070 c0fb1f5c c0fb1f48 c00618bc c005f2d4 00000070 00000070 c0fb1f74
[ 1131.210607] 1f54  c0fb1f60 c005eb98 c00617f8 c04c7960 00000070 c0fb1f94 c0fb1f78 c00107d8
[ 1131.219722]
[ 1131.219722] R4: 0xc0e9db80:
[ 1131.224456] db80  00000000 3b9aca00 c0e9dbac c0e9db98 80000093 c059aec0 ff676980 6b280000
[ 1131.233564] dba0  000000ee 00000000 c0e9dbdc c0e9dbb8 c00120bc c0289034 c0e86b30 4e979ce6
[ 1131.242674] dbc0  005b8d80 00000000 00000000 00000002 c0e9dbfc c0e9dbe0 c0041584 c004136c
[ 1131.251783] dbe0  00000000 00000002 c04bb3d0 c0e86b30 c0e9dc24 c0e9dc00 c0e86b30 4e98aed3
[ 1131.260892] dc00  bf1f8a18 bf1f8a18 c1862a10 c0e9dc0c c0e9dc0c 5f647674 326c3476 7665645f
[ 1131.270003] dc20  00000030 00000000 00000000 00000000 00000000 00000000 00000000 c0e9de74
[ 1131.279108] dc40  00000000 00000000 00000000 00000000 00000001 c0e9dc54 c0e9dc54 00000002
[ 1131.288215] dc60  00000000 00000000 c1862a00 00000000 00000000 00000001 c1b66800 c0e9dc7c
[ 1131.297325]
[ 1131.297325] R5: 0xc0e9dbfc:
[ 1131.302059] dbfc  4e98aed3 bf1f8a18 bf1f8a18 c1862a10 c0e9dc0c c0e9dc0c 5f647674 326c3476
[ 1131.311169] dc1c  7665645f 00000030 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.320275] dc3c  c0e9de74 00000000 00000000 00000000 00000000 00000001 c0e9dc54 c0e9dc54
[ 1131.329386] dc5c  00000002 00000000 00000000 c1862a00 00000000 00000000 00000001 c1b66800
[ 1131.338494] dc7c  c0e9dc7c c0e9dc7c 00000000 00013274 0000b4aa 00014485 00000000 00000000
[ 1131.347601] dc9c  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.356707] dcbc  00000001 00000000 000002d0 000001e0 00000001 00000000 00000000 000002d0
[ 1131.365810] dcdc  000001e0 0007e900 00000000 c0e98e60 00000001 00000017 00000000 00000000
[ 1131.374920]
[ 1131.374920] R6: 0xc0e9dbfc:
[ 1131.379654] dbfc  4e98aed3 bf1f8a18 bf1f8a18 c1862a10 c0e9dc0c c0e9dc0c 5f647674 326c3476
[ 1131.388767] dc1c  7665645f 00000030 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.397874] dc3c  c0e9de74 00000000 00000000 00000000 00000000 00000001 c0e9dc54 c0e9dc54
[ 1131.406983] dc5c  00000002 00000000 00000000 c1862a00 00000000 00000000 00000001 c1b66800
[ 1131.416091] dc7c  c0e9dc7c c0e9dc7c 00000000 00013274 0000b4aa 00014485 00000000 00000000
[ 1131.425201] dc9c  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.434307] dcbc  00000001 00000000 000002d0 000001e0 00000001 00000000 00000000 000002d0
[ 1131.443414] dcdc  000001e0 0007e900 00000000 c0e98e60 00000001 00000017 00000000 00000000
[ 1131.452524]
[ 1131.452524] R7: 0xc0e9d958:
[ 1131.457259] d958  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.466366] d978  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.475473] d998  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.484581] d9b8  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.493688] d9d8  00000000 00000000 00000000 00000000 00000000 00000000 c0e86b30 4ba7ea54
[ 1131.502796] d9f8  c0e9da2c 00000000 6fecf2e7 c0592e6c 60000013 c059cf88 c0592e6c c06524f0
[ 1131.511903] da18  c0592e6c 60000013 c0e9daa4 c0e9da30 c006ce8c c006bc78 00000041 c003f07c
[ 1131.521014] da38  00000001 c065250c c0e9da64 c0e9da50 c01a8dec c01a8d98 c18f0380 c18f0380
[ 1131.530127]
[ 1131.530127] R10: 0xc05935c1:
[ 1131.534957] 35c0  00100100 00200200 00000000 00000040 00000000 c02dafc4 00000000 00000000
[ 1131.544066] 35e0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.553173] 3600  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.562281] 3620  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.571390] 3640  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.580499] 3660  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.589608] 3680  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.598714] 36a0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.607822] 36c0  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 1131.616936] Process mjpg_streamer (pid: 255, stack limit = 0xc0fb01b8)
[ 1131.624173] Stack: (0xc0fb1ed8 to 0xc0fb2000)
[ 1131.629013] 1ec0:                                                       c0fdf040 c04c06a8
[ 1131.638093] 1ee0: 00000070 00000000 c0fb1f2c c0fb1ef8 c005f158 bf1f554c c1832df0 4774463a
[ 1131.647174] 1f00: c0fb1f34 c04c06a8 00000070 00000000 80808080 80808080 80808080 80808080
[ 1131.656257] 1f20: c0fb1f44 c0fb1f30 c005f2f4 c005f130 c04c06a8 00000070 c0fb1f5c c0fb1f48
[ 1131.665339] 1f40: c00618bc c005f2d4 00000070 00000070 c0fb1f74 c0fb1f60 c005eb98 c00617f8
[ 1131.674421] 1f60: c04c7960 00000070 c0fb1f94 c0fb1f78 c00107d8 c005eb80 c059eac0 c0fb1fb0
[ 1131.683503] 1f80: ffffffff 80808080 c0fb1fac c0fb1f98 c000a314 c0010778 b6fca0a4 20000010
[ 1131.692585] 1fa0: 00000000 c0fb1fb0 c000f6c8 c000a2e8 b6ccd920 b6de3930 00020fd0 00000010
[ 1131.701667] 1fc0: 80808080 80808080 80808080 80808080 80808080 80808080 80808080 80808080
[ 1131.710747] 1fe0: 00000000 b6b26868 b6f46174 b6fca0a4 20000010 ffffffff 00000000 00000000
[ 1131.719806] Backtrace:
[ 1131.722589] [<bf1f553c>] (tvd_isr+0x0/0x1a4 [tvin]) from [<c005f158>] (handle_irq_event_percpu+0x38/0x1a4)
[ 1131.733293]  r7:00000000 r6:00000070 r5:c04c06a8 r4:c0fdf040
[ 1131.739618] [<c005f120>] (handle_irq_event_percpu+0x0/0x1a4) from [<c005f2f4>] (handle_irq_event+0x30/0x40)
[ 1131.750446] [<c005f2c4>] (handle_irq_event+0x0/0x40) from [<c00618bc>] (handle_level_irq+0xd4/0xe4)
[ 1131.760469]  r5:00000070 r4:c04c06a8
[ 1131.764462] [<c00617e8>] (handle_level_irq+0x0/0xe4) from [<c005eb98>] (generic_handle_irq+0x28/0x38)
[ 1131.774678]  r5:00000070 r4:00000070
[ 1131.778687] [<c005eb70>] (generic_handle_irq+0x0/0x38) from [<c00107d8>] (handle_IRQ+0x70/0x88)
[ 1131.788328]  r5:00000070 r4:c04c7960
[ 1131.792324] [<c0010768>] (handle_IRQ+0x0/0x88) from [<c000a314>] (sun3i_handle_irq+0x3c/0x44)
[ 1131.801771]  r7:80808080 r6:ffffffff r5:c0fb1fb0 r4:c059eac0
[ 1131.808087] [<c000a2d8>] (sun3i_handle_irq+0x0/0x44) from [<c000f6c8>] (__irq_usr+0x48/0x60)
[ 1131.817442] Exception stack(0xc0fb1fb0 to 0xc0fb1ff8)
[ 1131.823052] 1fa0:                                     b6ccd920 b6de3930 00020fd0 00000010
[ 1131.832136] 1fc0: 80808080 80808080 80808080 80808080 80808080 80808080 80808080 80808080
[ 1131.841211] 1fe0: 00000000 b6b26868 b6f46174 b6fca0a4 20000010 ffffffff
[ 1131.848540]  r5:20000010 r4:b6fca0a4
[ 1131.852526] Code: e594507c e5153080 e2457fa9 e28320c8 (e59330c8)
[ 1131.859306] ---[ end trace 86da1e7699facbf8 ]---
[ 1131.864428] Kernel panic - not syncing: Fatal exception in interrupt

日志 : (

#43 全志 SOC » tiny200 tina 接tv 摄像头跑 mjpg-streamer 挂了 » 2021-04-14 12:08:26

uuid
回复: 1

安装TV输入驱动:

insmod videobuf2-core.ko
insmod videobuf2-memops.ko
insmod videobuf2-dma-contig.ko
insmod tvin.ko

LD_LIBRARY_PATH=/usr/lib/:$LD_LIBRARY_PATH mjpg_streamer -i "input_uvc.so  -d /dev/video4" -o "output_http.so -p 8080 -w /www/webcam/"


root@TinaLinux:/tmp# LD_LIBRARY_PATH=/usr/lib/:$LD_LIBRARY_PATH mjpg_streamer -i
 "input_uvc.so  -d /dev/video4" -o "output_http.so -p 8080 -w /www/webcam/"
MJPG Streamer Version: svn rev:
 i: Using V4L2 device.: /dev/video4
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: not limited
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
ioctl (-1060350460) retried 4 times - giving up: Resource temporarily unavailable)
 o: www-folder-path...: /www/webcam/
 o: HTTP TCP port.....: 8080
 o: username:password.: disabled
 o: commands..........: enabled

#44 Re: SigmaStar/SSD201/SSD202/SSD212 » 转自Q群的 SSD201/SSD202/SSD20X AD/DXP 原理图与PCB » 2021-02-08 17:59:34

@Gentlepig 应该是 屏蔽罩的.



QQ图片20210208175356.jpg

QQ图片20210208175344.jpg

QQ图片20210208175313.jpg

QQ图片20210208175325.jpg

以上图片转自 Q群 飘移小子

#47 Re: 全志 SOC » 写了一个简单的Linux memcpy 测试函数, 大家可以看看各种平台的memcpy拷贝速度 » 2021-01-28 19:12:49

#
# ./memtest 1
now test copy 1M bytes.
calculate time: 4373 us
#
#
# ./memtest 2
now test copy 2M bytes.
calculate time: 9216 us
#
# ./memtest 3
now test copy 3M bytes.
calculate time: 13578 us
#
# ./memtest 10
now test copy 10M bytes.
calculate time: 44411 us
#
# ./memtest 15
now test copy 15M bytes.
calculate time: 67031 us
#
# ./memtest 30
now test copy 30M bytes.
calculate time: 133734 us
#
# ./memtest 50
now test copy 50M bytes.
calculate time: 221139 us
#

奇怪, 为什么X3 比 V3s DDR3版本(S3) 更慢?

CONFIG_DRAM_CLK=552
CONFIG_DRAM_ZQ=15291
# CONFIG_DRAM_ODT_EN is not set
CONFIG_SYS_CLK_FREQ=1008000000

#48 Re: 全志 SOC » 写了一个简单的Linux memcpy 测试函数, 大家可以看看各种平台的memcpy拷贝速度 » 2021-01-28 09:09:25

微凉VeiLiang 说:

还有这回事,ddr3为什么会慢过ddr2

不好意思, 前面写错了。应该是同频率下,DDR3比DDR2快了一倍多.

#49 Re: 全志 SOC » 写了一个简单的Linux memcpy 测试函数, 大家可以看看各种平台的memcpy拷贝速度 » 2021-01-27 22:49:57

V3s DDR3 (相当于S3)
CPU 1GHz, DDR CLK 360MHz

# memtest 1
now test copy 1M bytes.
calculate time: 2458 us
#
# memtest 10
now test copy 10M bytes.
calculate time: 24788 us
#
#
# memtest 15
now test copy 15M bytes.
calculate time: 37431 us
#
# memtest 3
now test copy 3M bytes.
calculate time: 7528 us
#
#
# memtest 3
now test copy 3M bytes.
calculate time: 7294 us
#
#
# memtest 3
now test copy 3M bytes.
calculate time: 7329 us

同频率下,DDR2比DDR3快了一倍多.

#50 Re: 全志 SOC » 写了一个简单的Linux memcpy 测试函数, 大家可以看看各种平台的memcpy拷贝速度 » 2021-01-27 22:45:33

V3s DDR2
CPU 1GHz, DDR CLK 360MHz

# memtest 1
now test copy 1M bytes.
calculate time: 4300 us
#
#
#
# memtest 10
now test copy 10M bytes.
calculate time: 50673 us
#
#
#
# memtest 15
now test copy 15M bytes.
calculate time: 82828 us

#51 全志 SOC » 写了一个简单的Linux memcpy 测试函数, 大家可以看看各种平台的memcpy拷贝速度 » 2021-01-27 22:37:44

uuid
回复: 5

memtest.c

#include <string.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include <stdio.h>

#define ONE_MILLION   1000000
#define MEM_TEST_SIZE (100 * ONE_MILLION)

int main(int argc, char* argv[])
{
        if (argc < 2)
        {
                printf("usage: %s n (test n mega bytes)\n", argv[0]);
                exit(-1);
        }

        int n = abs(atoi(argv[1]));

        printf("now test copy %dM bytes.\n", n);

        uint8_t *src = (uint8_t *)malloc(n * ONE_MILLION);
        uint8_t *dst = (uint8_t *)malloc(n * ONE_MILLION);

        if(!src || !dst)
        {
                printf("alloc memory error!\n");
                exit(-2);
        }

        struct  timeval time_start;
        struct  timeval time_end;

        gettimeofday(&time_start,NULL);
        memcpy(dst, src, (n * ONE_MILLION));
        gettimeofday(&time_end,NULL);
        printf("calculate time: %ld us \n",
                (ONE_MILLION * time_end.tv_sec + time_end.tv_usec)-(ONE_MILLION*time_start.tv_sec + time_start.tv_usec)
              );

        free(dst);
        free(src);
        return 0;
 }

VMWARE + Ubuntu 18.04 测试:

$
$ ./memtest 1
now test copy 1M bytes.
calculate time: 665 us
$
$ ./memtest 10
now test copy 10M bytes.
calculate time: 6692 us
$
$ ./memtest 100
now test copy 100M bytes.
calculate time: 67354 us

#52 Re: 全志 SOC » 也发一个荔枝派zero 全志V3s 32M spi flash 固件,800x480 LCD, 开机自动运行 Qt analogclock » 2021-01-27 22:18:22

路漫漫 说:

V3s ENC28j60 网卡驱动成功, SPI接口连ENC28J60, PB5接ENC28J60 INT口:

&spi0 {
        status ="okay";

		eth1: enc28j60@0{
				compatible = "microchip,enc28j60";
				reg = <0x0>; /* CE0 */
				interrupt-parent = <&pio>;
				interrupts = <1 5 IRQ_TYPE_EDGE_FALLING>; /* (PB5) */
				gpios = <&pio 1 5 GPIO_ACTIVE_HIGH>;
				spi-max-frequency = <12000000>;
				status = "okay";
		};
#if 0
        mx25l25635e:mx25l25635e@0 {
                compatible = "jedec,spi-nor";
                reg = <0x0>;
                spi-max-frequency = <50000000>;
                #address-cells = <1>;
                #size-cells = <1>;
        };
#endif
};

https://whycan.cn/files/members/1842/QQ图片20200702160214.jpg

固件本站下载: V3s_tfcard_20200702151252.tgz

测试了一下, 真可以做WIFI路由器用 ^_^

只是没有web设置界面而已 :(

#58 Re: 好钜润半导体(TIKY) » TKM32F499配4.0寸IPS屏在RGB888模式下截屏功能 » 2021-01-14 23:52:34

Tiky 说:

感谢你的关注,已经开贴上传了

TKM32F499GT8评估板资料集
http://whycan.com/t_5861.html
(出处:哇酷开发者社区【好钜润半导体(TIKY)】)


资料好丰富喔

#60 Re: 技术人生/软件使用技巧/破解经验/技术吐槽/灌水 » 我是来砸店的,用 curl 模拟登录哇酷网 (whycan.com) » 2021-01-03 22:19:19

然后当前目录下面的cookie文件(已马赛克):

$ cat cookies
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_.whycan.com   TRUE    /       FALSE   1610893069      pun_cookie_a2a841       5564%7C1acedc8a3bd69b2bc99f6ffc01ba4806ac47dc12%7C1610893069%7C0178d2c4e16af69d25ca300e7d8fcbc531*****
#HttpOnly_.whycan.com   TRUE    /       FALSE   1609683469      pun_cookie_a2a841_track deleted

#61 Re: 全志 SOC » v3s 如何 把 spi flash rootfs 全部加载到 sdram ,如何打包 » 2021-01-03 22:15:59

荔枝派zero/小智极客S3/V3s使用sunxi-fel 借 u-boot 启动 Linux系统, 无需 spi flash / TF 卡
http://whycan.com/t_2388.html
(出处:哇酷开发者社区【全志 V3S/F1C100s/X3】)





这个就是全部加载到RAM跑

#62 技术人生/软件使用技巧/破解经验/技术吐槽/灌水 » 我是来砸店的,用 curl 模拟登录哇酷网 (whycan.com) » 2021-01-03 22:06:55

uuid
回复: 8

QQ截图20210103220056.png

QQ截图20210103220134.png


运行curl命令(密码已经打码):

curl  -L -b cookies -c cookies -d "form_sent=1&redirect_url=https%3A%2F%2Fwhycan.com%2Findex.php&req_username=uuid&req_password=*****&save_pass=1&login=%E7%99%BB%E5%BD%95" https://whycan.com/login.php?action=in

QQ截图20210103220600.png


登录成功!

#63 Re: 全志 SOC » 关于v3s emmc 驱动的问题 » 2021-01-01 00:13:21

wupaul2001 说:

设置EMMC使用UDA区启动

这样哦, 我去搜搜看。

#64 Re: 全志 SOC » 关于v3s emmc 驱动的问题 » 2020-12-31 22:57:34

wupaul2001 说:

u-boot里运行mmcpart 0 0 7 0

请教这个干嘛的呢?

#65 Re: 全志 SOC » licheepi-zero不输出声音 » 2020-12-30 22:03:51

首先确认是不是用alsa输出,

然后用tinymix 设置声卡寄存器:





请问全志V3s使用荔枝派最新的 linux 4.13-y 分支,如何支持声卡?
http://whycan.com/t_489.html#p1284
(出处:哇酷开发者社区【全志 V3S/F1C100s/X3】)

#67 Re: 全志 SOC » 荔枝派nano的SPI-Flash启动 » 2020-12-14 16:25:47

改用TF卡启动,看下有没有生成 /dev/mtdblockX 分区。

#69 Re: 全志 SOC » A33主线Linux跑起OpenGL/ES » 2020-12-10 23:26:10

Egl-example_output.png

https://wiki.maemo.org/SimpleGL_example


/* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 )
 * edited and commented by André Bergner [endboss]
 *
 * libraries needed:   libx11-dev, libgles2-dev
 *
 * compile with:   g++  -lX11 -lEGL -lGLESv2  egl-example.cpp
 */
 
#include  <iostream>
#include  <cstdlib>
#include  <cstring>
using namespace std;
 
#include  <cmath>
#include  <sys/time.h>
 
#include  <X11/Xlib.h>
#include  <X11/Xatom.h>
#include  <X11/Xutil.h>
 
#include  <GLES2/gl2.h>
#include  <EGL/egl.h>
 
 
 
const char vertex_src [] =
"                                        \
   attribute vec4        position;       \
   varying mediump vec2  pos;            \
   uniform vec4          offset;         \
                                         \
   void main()                           \
   {                                     \
      gl_Position = position + offset;   \
      pos = position.xy;                 \
   }                                     \
";
 
 
const char fragment_src [] =
"                                                      \
   varying mediump vec2    pos;                        \
   uniform mediump float   phase;                      \
                                                       \
   void  main()                                        \
   {                                                   \
      gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *     \
        cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)   \
             + atan(pos.y,pos.x) - phase );            \
   }                                                   \
";
//  some more formulas to play with...
//      cos( 20.*(pos.x*pos.x + pos.y*pos.y) - phase );
//      cos( 20.*sqrt(pos.x*pos.x + pos.y*pos.y) + atan(pos.y,pos.x) - phase );
//      cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y - 1.8*pos.x*pos.y*pos.y)
//            + atan(pos.y,pos.x) - phase );
 
 
void
print_shader_info_log (
   GLuint  shader      // handle to the shader
)
{
   GLint  length;
 
   glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , &length );
 
   if ( length ) {
      char* buffer  =  new char [ length ];
      glGetShaderInfoLog ( shader , length , NULL , buffer );
      cout << "shader info: " <<  buffer << flush;
      delete [] buffer;
 
      GLint success;
      glGetShaderiv( shader, GL_COMPILE_STATUS, &success );
      if ( success != GL_TRUE )   exit ( 1 );
   }
}
 
 
GLuint
load_shader (
   const char  *shader_source,
   GLenum       type
)
{
   GLuint  shader = glCreateShader( type );
 
   glShaderSource  ( shader , 1 , &shader_source , NULL );
   glCompileShader ( shader );
 
   print_shader_info_log ( shader );
 
   return shader;
}
 
 
Display    *x_display;
Window      win;
EGLDisplay  egl_display;
EGLContext  egl_context;
EGLSurface  egl_surface;
 
GLfloat
   norm_x    =  0.0,
   norm_y    =  0.0,
   offset_x  =  0.0,
   offset_y  =  0.0,
   p1_pos_x  =  0.0,
   p1_pos_y  =  0.0;
 
GLint
   phase_loc,
   offset_loc,
   position_loc;
 
 
bool        update_pos = false;
 
const float vertexArray[] = {
   0.0,  0.5,  0.0,
  -0.5,  0.0,  0.0,
   0.0, -0.5,  0.0,
   0.5,  0.0,  0.0,
   0.0,  0.5,  0.0 
};
 
 
void  render()
{
   static float  phase = 0;
   static int    donesetup = 0;
 
   static XWindowAttributes gwa;
 
   //// draw
 
   if ( !donesetup ) {
      XWindowAttributes  gwa;
      XGetWindowAttributes ( x_display , win , &gwa );
      glViewport ( 0 , 0 , gwa.width , gwa.height );
      glClearColor ( 0.08 , 0.06 , 0.07 , 1.);    // background color
      donesetup = 1;
   }
   glClear ( GL_COLOR_BUFFER_BIT );
 
   glUniform1f ( phase_loc , phase );  // write the value of phase to the shaders phase
   phase  =  fmodf ( phase + 0.5f , 2.f * 3.141f );    // and update the local variable
 
   if ( update_pos ) {  // if the position of the texture has changed due to user action
      GLfloat old_offset_x  =  offset_x;
      GLfloat old_offset_y  =  offset_y;
 
      offset_x  =  norm_x - p1_pos_x;
      offset_y  =  norm_y - p1_pos_y;
 
      p1_pos_x  =  norm_x;
      p1_pos_y  =  norm_y;
 
      offset_x  +=  old_offset_x;
      offset_y  +=  old_offset_y;
 
      update_pos = false;
   }
 
   glUniform4f ( offset_loc  ,  offset_x , offset_y , 0.0 , 0.0 );
 
   glVertexAttribPointer ( position_loc, 3, GL_FLOAT, false, 0, vertexArray );
   glEnableVertexAttribArray ( position_loc );
   glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 );
 
   eglSwapBuffers ( egl_display, egl_surface );  // get the rendered buffer to the screen
}
 
 
////////////////////////////////////////////////////////////////////////////////////////////
 
 
int  main()
{
   ///////  the X11 part  //////////////////////////////////////////////////////////////////
   // in the first part the program opens a connection to the X11 window manager
   //
 
   x_display = XOpenDisplay ( NULL );   // open the standard display (the primary screen)
   if ( x_display == NULL ) {
      cerr << "cannot connect to X server" << endl;
      return 1;
   }
 
   Window root  =  DefaultRootWindow( x_display );   // get the root window (usually the whole screen)
 
   XSetWindowAttributes  swa;
   swa.event_mask  =  ExposureMask | PointerMotionMask | KeyPressMask;
 
   win  =  XCreateWindow (   // create a window with the provided parameters
              x_display, root,
              0, 0, 800, 480,   0,
              CopyFromParent, InputOutput,
              CopyFromParent, CWEventMask,
              &swa );
 
   XSetWindowAttributes  xattr;
   Atom  atom;
   int   one = 1;
 
   xattr.override_redirect = False;
   XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );
 
   atom = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", True );
   XChangeProperty (
      x_display, win,
      XInternAtom ( x_display, "_NET_WM_STATE", True ),
      XA_ATOM,  32,  PropModeReplace,
      (unsigned char*) &atom,  1 );
 
   XChangeProperty (
      x_display, win,
      XInternAtom ( x_display, "_HILDON_NON_COMPOSITED_WINDOW", False ),
      XA_INTEGER,  32,  PropModeReplace,
      (unsigned char*) &one,  1);
 
   XWMHints hints;
   hints.input = True;
   hints.flags = InputHint;
   XSetWMHints(x_display, win, &hints);
 
   XMapWindow ( x_display , win );             // make the window visible on the screen
   XStoreName ( x_display , win , "GL test" ); // give the window a name
 
   //// get identifiers for the provided atom name strings
   Atom wm_state   = XInternAtom ( x_display, "_NET_WM_STATE", False );
   Atom fullscreen = XInternAtom ( x_display, "_NET_WM_STATE_FULLSCREEN", False );
 
   XEvent xev;
   memset ( &xev, 0, sizeof(xev) );
 
   xev.type                 = ClientMessage;
   xev.xclient.window       = win;
   xev.xclient.message_type = wm_state;
   xev.xclient.format       = 32;
   xev.xclient.data.l[0]    = 1;
   xev.xclient.data.l[1]    = fullscreen;
   XSendEvent (                // send an event mask to the X-server
      x_display,
      DefaultRootWindow ( x_display ),
      False,
      SubstructureNotifyMask,
      &xev );
 
 
   ///////  the egl part  //////////////////////////////////////////////////////////////////
   //  egl provides an interface to connect the graphics related functionality of openGL ES
   //  with the windowing interface and functionality of the native operation system (X11
   //  in our case.
 
   egl_display  =  eglGetDisplay( (EGLNativeDisplayType) x_display );
   if ( egl_display == EGL_NO_DISPLAY ) {
      cerr << "Got no EGL display." << endl;
      return 1;
   }
 
   if ( !eglInitialize( egl_display, NULL, NULL ) ) {
      cerr << "Unable to initialize EGL" << endl;
      return 1;
   }
 
   EGLint attr[] = {       // some attributes to set up our egl-interface
      EGL_BUFFER_SIZE, 16,
      EGL_RENDERABLE_TYPE,
      EGL_OPENGL_ES2_BIT,
      EGL_NONE
   };
 
   EGLConfig  ecfg;
   EGLint     num_config;
   if ( !eglChooseConfig( egl_display, attr, &ecfg, 1, &num_config ) ) {
      cerr << "Failed to choose config (eglError: " << eglGetError() << ")" << endl;
      return 1;
   }
 
   if ( num_config != 1 ) {
      cerr << "Didn't get exactly one config, but " << num_config << endl;
      return 1;
   }
 
   egl_surface = eglCreateWindowSurface ( egl_display, ecfg, win, NULL );
   if ( egl_surface == EGL_NO_SURFACE ) {
      cerr << "Unable to create EGL surface (eglError: " << eglGetError() << ")" << endl;
      return 1;
   }
 
   //// egl-contexts collect all state descriptions needed required for operation
   EGLint ctxattr[] = {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
   egl_context = eglCreateContext ( egl_display, ecfg, EGL_NO_CONTEXT, ctxattr );
   if ( egl_context == EGL_NO_CONTEXT ) {
      cerr << "Unable to create EGL context (eglError: " << eglGetError() << ")" << endl;
      return 1;
   }
 
   //// associate the egl-context with the egl-surface
   eglMakeCurrent( egl_display, egl_surface, egl_surface, egl_context );
 
 
   ///////  the openGL part  ///////////////////////////////////////////////////////////////
 
   GLuint vertexShader   = load_shader ( vertex_src , GL_VERTEX_SHADER  );     // load vertex shader
   GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER );  // load fragment shader
 
   GLuint shaderProgram  = glCreateProgram ();                 // create program object
   glAttachShader ( shaderProgram, vertexShader );             // and attach both...
   glAttachShader ( shaderProgram, fragmentShader );           // ... shaders to it
 
   glLinkProgram ( shaderProgram );    // link the program
   glUseProgram  ( shaderProgram );    // and select it for usage
 
   //// now get the locations (kind of handle) of the shaders variables
   position_loc  = glGetAttribLocation  ( shaderProgram , "position" );
   phase_loc     = glGetUniformLocation ( shaderProgram , "phase"    );
   offset_loc    = glGetUniformLocation ( shaderProgram , "offset"   );
   if ( position_loc < 0  ||  phase_loc < 0  ||  offset_loc < 0 ) {
      cerr << "Unable to get uniform location" << endl;
      return 1;
   }
 
 
   const float
      window_width  = 800.0,
      window_height = 480.0;
 
   //// this is needed for time measuring  -->  frames per second
   struct  timezone  tz;
   timeval  t1, t2;
   gettimeofday ( &t1 , &tz );
   int  num_frames = 0;
 
   bool quit = false;
   while ( !quit ) {    // the main loop
 
      while ( XPending ( x_display ) ) {   // check for events from the x-server
 
         XEvent  xev;
         XNextEvent( x_display, &xev );
 
         if ( xev.type == MotionNotify ) {  // if mouse has moved
//            cout << "move to: << xev.xmotion.x << "," << xev.xmotion.y << endl;
            GLfloat window_y  =  (window_height - xev.xmotion.y) - window_height / 2.0;
            norm_y            =  window_y / (window_height / 2.0);
            GLfloat window_x  =  xev.xmotion.x - window_width / 2.0;
            norm_x            =  window_x / (window_width / 2.0);
            update_pos = true;
         }
 
         if ( xev.type == KeyPress )   quit = true;
      }
 
      render();   // now we finally put something on the screen
 
      if ( ++num_frames % 100 == 0 ) {
         gettimeofday( &t2, &tz );
         float dt  =  t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
         cout << "fps: " << num_frames / dt << endl;
         num_frames = 0;
         t1 = t2;
      }
//      usleep( 1000*10 );
   }
 
 
   ////  cleaning up...
   eglDestroyContext ( egl_display, egl_context );
   eglDestroySurface ( egl_display, egl_surface );
   eglTerminate      ( egl_display );
   XDestroyWindow    ( x_display, win );
   XCloseDisplay     ( x_display );
 
   return 0;
}

编译指令:
g++ -o test4 test4.c  -lX11 -lGL -lEGL

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn