Accessing ethernet phy driver from linux user space - linux

i want to access ethernet phy driver from linux user space,
In uboot we can directly access phy registers using mii commands
similarly i want to read and write phy registers from linux user space .
cause there is no major or minor number comes in case of phy driver(maybe cause its a network driver)
how to do it.and is it possible

There are the following ioctl requests for that purpose:
#define SIOCGMIIREG 0x8948 /* Read MII PHY register. */
#define SIOCSMIIREG 0x8949 /* Write MII PHY register. */
And MII register constants are defined in:
#include <linux/mii.h>
Example:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <linux/mii.h>
#include <linux/sockios.h>
int main()
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, "eth1");
struct mii_ioctl_data* mii = (struct mii_ioctl_data*)(&ifr.ifr_data);
mii->phy_id = 1;
mii->reg_num = MII_BMSR;
mii->val_in = 0;
mii->val_out = 0;
const int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd != -1)
{
if (ioctl(fd, SIOCGMIIREG, &ifr) != -1)
{
printf("MII_BMSR = 0x%04hX \n", mii->val_out);
printf("BMSR_LSTATUS = %d \n", (mii->val_out & BMSR_LSTATUS) ? 1 : 0);
}
close(fd);
}
return 0;
}

Try to use mii-tool or ethtool. Look at the sources of those programs how to get access to phy api.

Related

NETLINK_NFLOG support in Linux 4.14

I've this program which runs fine on Linux 2.6.34. While porting this program to 4.14, socket creation is giving error "Error: : Protocol not supported". As per http://man7.org/linux/man-pages/man7/netlink.7.html
NETLINK_NFLOG (up to and including Linux 3.16)
Netfilter/iptables ULOG.
Do we know what is the alternative in 4.14 ?
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <pthread.h>
#include <netinet/ip.h>
#include <linux/types.h>
#include <linux/netlink.h>
int main()
{
struct sockaddr_nl addr;
int mypid;
int status;
int sockfd = -1;
/* mypid = getpid(); */
mypid = pthread_self();
sockfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NFLOG);
if (sockfd <= 0) {
printf("netlink socket() failed - rc:%d, errno:%d\n",
sockfd, errno);
perror("Error: ");
return (-1);
}
/* set up socket address */
memset(&addr, 0, sizeof (addr));
addr.nl_pid = mypid;
addr.nl_family = AF_NETLINK;
/*
nl_groups is the multicast
group ID to which the ULOG
messages will be sent.It
is bitmap of hexadecimal
format
*/
addr.nl_groups = 1;
/* bind socket to listen on
* multicast group 1 */
status = bind(sockfd, (struct sockaddr *)&addr, sizeof (addr));
if (status < 0) {
perror("bind:");
close(sockfd);
return (-1);
}
printf("socket bind successful\n");
close(sockfd);
return (0);
}
I tried to browse kernel source but couldn't identify.
I've below config
CONFIG_NETFILTER=y
# CONFIG_NETFILTER_ADVANCED is not set
CONFIG_NETFILTER_INGRESS=y
CONFIG_NETFILTER_NETLINK=y
CONFIG_NETFILTER_NETLINK_LOG=y
# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XT_MARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_LOG=y
CONFIG_NETFILTER_XT_NAT=y
# CONFIG_NETFILTER_XT_TARGET_NETMAP is not set
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
# CONFIG_NETFILTER_XT_TARGET_REDIRECT is not set
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
NETLINK_NFLOG (up to and including Linux 3.16)
see worked example in libnml

Data transfer between Processor and FPGA through GPMC using EDMA

We are working on a board containing AM3359 processor.
SDK we are using is ti-processor-sdk-linux-am335x-evm-05.00.00.15.
Our customer wants to see the throughput of the data transfer between processor (AM3359) and FPGA connected through 8 GPMC lines using EDMA
All we want now is to implement GPMC_EDMA data transfer program as per the below flow.
Processor and FPGA lines
Processor booted ----> Run GPMC_EDMA Data transfer program ----> Complete data transfer ----> Calculate throughput.
Here is my code for transferring data to FPGA through 8 GPMC lines.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <termios.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#include <sys/mman.h>
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
int verbose = 0;
#define BUF_SIZE 4096
int main(){
int i,fd;char ch;
int buf[BUF_SIZE];
volatile uint8_t *map_base;
int a=1;
for(i=0;i<BUF_SIZE;i++){
if(i%100==0){
a++;
printf("i: %d, a: %d\n",i,a);
}
buf[i]=a;
}
//buf[BUF_SIZE]=43;
if((fd=open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
printf("Error in opening gpmc\n");return 0;
}
printf("Successfully opened\n");
map_base =(uint8_t *) mmap((void*)0x01000000, 0x01000000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x01000000);
if(map_base == (void *) -1) FATAL;
if (verbose) {
printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
}
volatile uint32_t *p32 = (uint32_t *) &map_base[0x0800];
//while(1/*(ch=getchar())!='\n'*/){
//*p32 = 0x1;
for(i=0;i<BUF_SIZE;i++){
*p32 = buf[i];
}
printf("Sent %d bytes\n",BUF_SIZE);
//}
printf("Closing FD\n");
close(fd);
}
Someone kindly help me to proceed further as we have a severe time restriction and also we are new to this one.
Regards
Vamsi

UART reply includes previous command?

I am trying to read from a UART device in a Linux environment using a C program, but I experience different results respect to communicating to the UART using screen.
The C code I use to test the UART communication is the following:
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <getopt.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <signal.h>
#include <ctype.h>
bool loop;
void sigHandler(int32_t sig)
{
if(sig == SIGINT)
{
printf("Catched SIGINT");
loop = false;
}
}
int main(int argc, char *argv[])
{
char *devname = argv[1];
int fd = -1;
int nread = -1;
int nwrite = -1;
int ret;
struct termios t_new = {0};
struct termios t_old = {0};
signal(SIGINT, sigHandler);
fd = open(devname, O_RDWR | O_NOCTTY |O_NONBLOCK);
if(fd > 0)
{
printf("TTY open ! Configuring TTY");
}
else
{
fd = -1;
return 1;
}
ret = tcgetattr(fd, &t_old);
if(ret < 0)
{
perror("tcgetattr ");
close(fd);
fd = -1;
return 1;
}
t_new = t_old;
t_new.c_cflag = (B9600 | CS8 | CREAD );
t_new.c_oflag = 0;
t_new.c_iflag = 0;
t_new.c_lflag = 0;
ret = tcsetattr(fd, TCSANOW, &t_new);
loop = true;
while(loop)
{
char s[] = "at+gmi=?\r\n";
nwrite = write(fd, s, strlen(s));
if(nwrite == strlen(s))
{
fd_set rfd;
struct timeval tm = {.tv_sec = 0, .tv_usec = 500000};
FD_ZERO(&rfd);
FD_SET(fd, &rfd);
char buffer[64] = {0};
if(select(fd + 1, &rfd, NULL, NULL, &tm) > 0)
nread = read(fd, buffer, sizeof(buffer));
if(nread > 0)
printf("Reply is: %s\n", buffer);
}
usleep(500000);
}
}
But when I read the reply, it always includes the string I have sent.
I don't experience this problem using screen.
What is the best way to read from an UART in C using Linux ?
Could the multiplexed way (using select) causing the problems ?
EDIT
For completeness, the output is:
Reply is: at+gmi=?
OK
Also, sometimes I don't read anything.
But when I read the reply, it always includes the string I have sent.
Since your termios configuration obliterated the local echo attributes and you're sending an AT modem command, you should try sending an ATE0 command to disable echoing by the modem.
I don't experience this problem using screen.
This observation confirms that the connected modem has its echoing enabled.
The AT command is echoed (by the modem) as you type, but you don't object to this received data in this situation (because you want to see what you type).
If the modem did not have echoing enabled, then you would be complaining that what you type in screen was not visible.
IOW echo is desired when using a terminal emulator program (such as screen), but echoing needs to be disabled when sending data by a program.
What is the best way to read from an UART in C using Linux ?
(Technically you are not reading from a "UART", but rather from a serial terminal that fully buffers all input and output.)
Code that conforms to POSIX standard as described in Setting Terminal Modes Properly
and Serial Programming Guide for POSIX Operating Systems would be far better that what you have now.
I'm surprised that it works at all (e.g. CREAD is not enabled).
Could the multiplexed way (using select) causing the problems ?
Not the echo "problem".
Your program does not do anything that requires using select() and nonblocking mode.
Also, sometimes I don't read anything.
When you write code that is not POSIX compliant, you should not expect reliable program behavior.

Receive IP packets on a TUN / TAP interface when the destination IP is not the IP assigned to the interface

First of all, I create the virtual interface tuntap using commands:
#ip tuntap add inter_virt1 mode tap
#ip link set inter_virt1 up
#ifconfig inter_virt1 172.16.2.40/24
If I do ping over 172.16.2.40, I get response:
root#enri-VirtualBox:/home/enri# ping 172.16.2.40
PING 172.16.2.40 (172.16.2.40) 56(84) bytes of data.
64 bytes from 172.16.2.40: icmp_seq=1 ttl=64 time=0.091 ms
64 bytes from 172.16.2.40: icmp_seq=2 ttl=64 time=0.108 ms
64 bytes from 172.16.2.40: icmp_seq=3 ttl=64 time=0.110 ms
^C
--- 172.16.2.40 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.091/0.103/0.110/0.008 ms
However using the following code, I get not receive anything:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char *argv[]){
int fd, ret, j;
struct sockaddr_ll interfaz;
struct ifreq ifr;
char *nameInterfaz = "inter_virt1";
char buffer[5000];
if((fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IP))) == -1){
perror("socket");
exit(1);
}
strcpy(ifr.ifr_name, nameInterfaz);
if((ret = ioctl(fd, SIOCGIFINDEX, &ifr)) == -1){
perror("ioctl");
exit(1);
}
memset(&interfaz, 0, sizeof(interfaz));
interfaz.sll_family = AF_PACKET;
interfaz.sll_protocol = htons(ETH_P_IP);
interfaz.sll_ifindex = ifr.ifr_ifindex;
if((ret = bind(fd, (struct sockaddr *)&interfaz, sizeof(interfaz))) == -1){
perror("bind");
exit(1);
}
while(1){
if((ret = recvfrom(fd, buffer, 5000, 0, NULL, NULL)) == -1){
perror("recvfrom");
exit(1);
}
printf("%d bytes received\n", ret);
for(j=0; j<ret; j++){
printf("%d] %d, ", j, (unsigned char)buffer[j]);
}
printf("\n\n");
}
return 0;
}
I have also tried to send datagrams (UDP) to 172.16.2.40 using socket
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
int main(int argc, char *argv[]){
int sd;
struct sockaddr_in dir_serv, dir_propia;
char *dir_ip_serv = "172.16.2.40", dir_propia = "192.168.1.2";
char buffer[2000];
if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket");
exit(1);
}
memset((char *)&dir_serv, 0, sizeof(dir_serv));
dir_serv.sin_family = AF_INET;
dir_serv.sin_port = htons(7012);
dir_serv.sin_addr.s_addr = inet_addr(dir_ip_serv);
memset((char *)&dir_propia, 0, sizeof(dir_propia));
dir_propia.sin_family = AF_INET;
dir_propia.sin_port = htons(7011);
dir_propia.sin_addr.s_addr = inet_addr(dir_ip_propia);
if(bind(sd, (struct sockaddr *)&dir_propia, sizeof(struct sockaddr_in)) == -1){
perror("bind");
exit(1);
}
printf("Introduce text\n");
scanf("%s", buffer);
if(sendto(sd, buffer, strlen(buffer), 0, (struct sockaddr *)&dir_serv, sizeof(struct sockaddr_in)) == -1){
perror("sendto");
exit(1);
}
return 0;
}
But I do not get anything. My ultimate goal is to receive packets addressed to the virtual interface when the destination IP address is or is not the IP address assigned to the virtual interface.
As a general point, if you use SOCK_DGRAM and bind() you will only receive packets addressed to the interface's IP address, as you are letting the kernel process the packet at the IP layer. The kernel will (broadly speaking) only relay packets addressed to a local interface IP address to the upper layers, and then will either forward (using the routing table) or discard other packets, depending on whether ip forwarding has been set up.
If you want to receive packets that are not addressed to the interface in question you should remove the IP numbering from the tunnel interface and use SOCK_RAW (see here for details) or pcap (see here for details) to receive them.
I think what you are trying to do is a third way to do this, i.e. use a tun/tap device. Here you need to route the packets into the tun / tap device, and your user mode code needs to read the user end of that. But your code does not appear to be doing that. In order to do this, you need to allocate the tun/tap device. See for instance here (see how tun_fd is produced from tun_alloc). You can't just bind to the interface side of the tun/tap device and magically assume it will work.

Headphone or mic detection connected via 3.5 mm jack linux

I have written a small program that informs when any headphone or mic is connected or not.
I provide a file path to identify, is there any way to know through a C program which file path is for mic or headphone?
Here is the program:
#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd = -1;
char name[256]= {'\0'};
struct input_event event;
/*On my system
/dev/input/event6 for headphone
/dev/input/event5 for mic
*/
if ((fd = open("/dev/input/event6", O_RDONLY)) < 0) {
perror("evdev open");
exit(1);
}
if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
perror("evdev ioctl");
}
printf("The device name on path %s is === %s\n Now Plug in or Plug out the device\n",
argv[1],name);
// while(1)
{
read(fd, &event, sizeof(struct input_event));
printf("Event type is %d\n", event.type);
printf("Event code is %d\n", event.code);
printf("Event value is %d\n", event.value);
}
close(fd);
return 0;
}
Here i need to provide path in open, I want my program should identify the path of the mic or headphone. Is there anyway to do this?
It would be great to have some help.
thanks,

Resources