I am trying to record sound with an ada fruit SPH6045 microphone and a Raspberry Pi Pico. I am following this git hub page however when I open the main.cpp code in Arduino IDE and compile I am getting the following error.
C:\Users\Brett J\Documents\Arduino\Rasbery Pi mic\Rasbery Pi mic.ino:10:10: fatal error: sph0645.pio.h: No such file or directory
10 | #include "sph0645.pio.h"
| ^~~~~~~~~~~~~~~
compilation terminated.
exit status 1
Compilation error: sph0645.pio.h: No such file or directory
I downloaded and extracted the zip file and saved it in the arduino librarys folder but that did not work. So then I tried to save it in the folder it is looking for it in and still no luck. I am new to raspberry pi's but am very familiar with the arduino IDE.The code is as follows.
#include "pico/time.h"
#include "pico/stdlib.h"
#include <stdio.h>
#include <inttypes.h>
#include <vector>
#include "hardware/clocks.h"
#include "hardware/pio.h"
#include "hardware/spi.h"
#include "hardware/uart.h"
#include "sph0645.pio.h"
#include <algorithm>
#include "hardware/dma.h"
#define PIN_DATA_OUT 2
#define PIN_SCLK 3
#define PIN_WS 4
#define printu(var) printf("%s: %lu\n", (#var), (size_t) (var))
#define bswap(x) \
((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) \
| (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24))
size_t clk;
PIO pio = pio0;
uint sm;
uint dma_chan;
#define BLOCK_SIZE (48000)
void init() {
stdio_uart_init_full(uart0, 921600, 0, 1);
/* stdio_init_all(); */
clk = clock_get_hz(clk_sys);
dma_chan = dma_claim_unused_channel(true);
}
static void start_dma(int32_t* buf, size_t len) {
dma_channel_config c = dma_channel_get_default_config(dma_chan);
channel_config_set_read_increment(&c, false);
channel_config_set_write_increment(&c, true);
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false));
dma_channel_configure(dma_chan, &c, buf, &pio->rxf[sm], len, true);
}
static void finalize_dma() {
dma_channel_wait_for_finish_blocking(dma_chan);
}
static void print_samples(int32_t* samples, size_t len) {
for (size_t i = 0; i < len; i++) {
auto val = samples[i];
printf("%d\t%X\n", val, val);
}
/* printf("("); */
/* for (size_t i = 0; i < len; i++) { */
/* printf("%d, ", samples[i]); */
/* /1* printf("%08X, ", samples[i]); *1/ */
/* } */
/* printf(")\n"); */
}
static void normalize(int32_t* samples, size_t len) {
for (int i = 0; i < 10; i++) {
start_dma(samples, len);
finalize_dma();
}
}
int main() {
init();
auto offset = pio_add_program(pio, &i2s_program);
sm = pio_claim_unused_sm(pio, true);
i2s_program_init(pio, sm, offset, PIN_DATA_OUT, PIN_SCLK);
/* start_dma(samples, BLOCK_SIZE); */
/* finalize_dma(); */
/* normalize(samples, BLOCK_SIZE); */
int32_t samples[BLOCK_SIZE] = {0};
auto start_time = time_us_32();
for (size_t i = 0; i < BLOCK_SIZE; i++) {
uint32_t val = pio_sm_get_blocking(pio, sm);
samples[i] = *((int32_t *) &val);
}
/* printf("%lu\n", time_us_32() - start_time); */
/* for (size_t i = 0; i < BLOCK_SIZE; i++) { */
/* samples[i] = pio_sm_get_blocking(pio, sm); */
/* } */
print_samples(samples, BLOCK_SIZE);
return 0;
}`
https://github.com/vijaymarupudi/sph0645-pico-troubleshooting
Related
Recently, I am trying to use bpf ringbuf in uprobe example of libbpf. But when running, error occurred which is "libbpf: load bpf program failed: Invalid argument". I have no idea why this happened. Could anyone help? Below is my test code.
Kernel space code: uprobe.bpf.c, define a rb struct, and use bpf_ringbuf_reserve in uprobe code block.
#include <linux/bpf.h>
#include <linux/ptrace.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
char LICENSE[] SEC("license") = "Dual BSD/GPL";
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
SEC("uprobe/func")
int BPF_KPROBE(uprobe, int a, int b)
{
__u64* e = bpf_ringbuf_reserve(&rb, sizeof(__u64), 0);
if (!e)
return 0;
bpf_printk("UPROBE ENTRY: a = %d, b = %d\n", a, b);
return 0;
}
SEC("uretprobe/func")
int BPF_KRETPROBE(uretprobe, int ret)
{
bpf_printk("UPROBE EXIT: return = %d\n", ret);
return 0;
}
User space code: uprobe.c
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "uprobe.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
static void bump_memlock_rlimit(void)
{
struct rlimit rlim_new = {
.rlim_cur = RLIM_INFINITY,
.rlim_max = RLIM_INFINITY,
};
if (setrlimit(RLIMIT_MEMLOCK, &rlim_new)) {
fprintf(stderr, "Failed to increase RLIMIT_MEMLOCK limit!\n");
exit(1);
}
}
/* Find process's base load address. We use /proc/self/maps for that,
* searching for the first executable (r-xp) memory mapping:
*
* 5574fd254000-5574fd258000 r-xp 00002000 fd:01 668759 /usr/bin/cat
* ^^^^^^^^^^^^ ^^^^^^^^
*
* Subtracting that region's offset (4th column) from its absolute start
* memory address (1st column) gives us the process's base load address.
*/
static long get_base_addr() {
size_t start, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%*x %s %zx %*[^\n]\n", &start, buf, &offset) == 3) {
if (strcmp(buf, "r-xp") == 0) {
fclose(f);
return start - offset;
}
}
fclose(f);
return -1;
}
static int handle_event(void *ctx, void *data, size_t data_sz)
{
return 0;
}
/* It's a global function to make sure compiler doesn't inline it. */
int uprobed_function(int a, int b)
{
return a + b;
}
int main(int argc, char **argv)
{
struct ring_buffer *rb = NULL;
struct uprobe_bpf *skel;
long base_addr, uprobe_offset;
int err, i;
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Bump RLIMIT_MEMLOCK to allow BPF sub-system to do anything */
bump_memlock_rlimit();
/* Load and verify BPF application */
skel = uprobe_bpf__open_and_load();
if (!skel) {
fprintf(stderr, "Failed to open and load BPF skeleton\n");
return 1;
}
base_addr = get_base_addr();
if (base_addr < 0) {
fprintf(stderr, "Failed to determine process's load address\n");
err = base_addr;
goto cleanup;
}
/* uprobe/uretprobe expects relative offset of the function to attach
* to. This offset is relateve to the process's base load address. So
* easy way to do this is to take an absolute address of the desired
* function and substract base load address from it. If we were to
* parse ELF to calculate this function, we'd need to add .text
* section offset and function's offset within .text ELF section.
*/
uprobe_offset = (long)&uprobed_function - base_addr;
/* Attach tracepoint handler */
skel->links.uprobe = bpf_program__attach_uprobe(skel->progs.uprobe,
false /* not uretprobe */,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* we can also attach uprobe/uretprobe to any existing or future
* processes that use the same binary executable; to do that we need
* to specify -1 as PID, as we do here
*/
skel->links.uretprobe = bpf_program__attach_uprobe(skel->progs.uretprobe,
true /* uretprobe */,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset);
err = libbpf_get_error(skel->links.uretprobe);
if (err) {
fprintf(stderr, "Failed to attach uprobe: %d\n", err);
goto cleanup;
}
/* Set up ring buffer polling */
rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event, NULL, NULL);
if (!rb) {
err = -1;
fprintf(stderr, "Failed to create ring buffer\n");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` "
"to see output of the BPF programs.\n");
for (i = 0; ; i++) {
err = ring_buffer__poll(rb, 100 /* timeout, ms */);
/* trigger our BPF programs */
fprintf(stderr, ".");
uprobed_function(i, i + 1);
sleep(1);
}
cleanup:
ring_buffer__free(rb);
uprobe_bpf__destroy(skel);
return -err;
}
I don't understand why the scanf call causes segmentation error. Tried making a separate file with only int number and scanf and it worked no problem. Really confused here need help. I use pointer in the scanf parameter so I'm suspecting the error might come from the interaction between scanf and shared memory somehow?
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <semaphore.h>
int main() {
const char *name = "message";
const char *names = "sem";
const int SIZE = 4096;
const int size = 1;
int number;
int shm_fd1;
int shm_fd2;
char *ptr; // Pointer to shared memory
sem_t *sem;
/* create the shared memory segment */
shm_fd1 = shm_open(name, O_CREAT | O_RDWR, 0666);
shm_fd2 = shm_open(names, O_CREAT | O_RDWR, 0666);
/* configure the size of the shared memory segment */
ftruncate(shm_fd1, SIZE);
ftruncate(shm_fd2, size);
/* initialize semaphore */
if (sem_init(sem, 1, 1) < 0) { // 1 = multiprocess
fprintf(stderr, "ERROR: could not initialize semaphore.\n");
exit(0);
}
/* now map the shared memory segment in the address space of the process */
ptr = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd1, 0);
sem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd2, 0);
if (ptr == MAP_FAILED) {
printf("Map failed\n");
return -1;
}
if (sem == MAP_FAILED) {
printf("Map failed\n");
return -1;
}
strcpy(ptr, "Hello from the server\n");
/* store and read from the shared memory region */
printf("Message: %s\n", ptr);
printf("0. Quit\n 1. Change message\n 2. Check message\n");
printf("Type an integer: ");
scanf("%d", &number); //confirmed this causes the error
if I remove the line above the program runs no problem. the part alone also works fine apart from this file.
if (number == 1) {
sem_wait(sem);
printf("Enter your message: ");
scanf("%s", ptr);
sem_post(sem);
}
else if (number == 2) {
printf("Message: %s\n", ptr);
}
else {
/*break;*/
}
/* remove the shared memory segment */
if (shm_unlink(name) == -1) {
printf("Error removing %s\n",name);
exit(-1);
}
return 0;
}
I am trying to map reserved memory (30M with offset of 2G) at boot time (boot kernel parameters mem=2G memmap=30M$2G) to user space using the remap_pfn_range, bellow is my driver code:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
// #include <asm/error.h>
#define MAP_MAJOR 150
#define RAW_DATA_SIZE 0x1E00000 // 30 Mo
#define RAW_DATA_OFFSET 0x80000000 //2G
int results;
static void *rawdataStart = NULL;
static int map_mmap(struct file *filp, struct vm_area_struct *vma);
struct file_operations map_fops = {
.open = nonseekable_open,
.mmap = map_mmap
};
static int map_mmap(struct file *filp, struct vm_area_struct *vma) {
if (rawdataStart == NULL) {
printk(KERN_ERR "Memory not mapped!\n");
return -EAGAIN;
}
if ((vma->vm_end - vma->vm_start) != RAW_DATA_SIZE) {
printk(KERN_ERR "Error: sizes don't match (buffer size = %d, requested size = %lu)\n", RAW_DATA_SIZE, vma->vm_end - vma->vm_start);
return -EAGAIN;
}
results = remap_pfn_range(vma, vma->vm_start, RAW_DATA_OFFSET >> PAGE_SHIFT, RAW_DATA_SIZE, PAGE_SHARED);
if (results != 0) {
printk(KERN_ERR "Error in calling remap_pfn_range: returned %d\n", results);
return -EAGAIN;
}
return 0;
}
static int __init map_init(void)
{
printk("init map module\n");
if (register_chrdev(MAP_MAJOR,"mapReserved", &map_fops) <0 )
{
printk("unable to get major for map module\n");
return -EBUSY;
}
rawdataStart = ioremap(RAW_DATA_OFFSET, RAW_DATA_SIZE);
if (rawdataStart == NULL) {
printk(KERN_ERR "Unable to remap memory\n");
return 1;
}
printk(KERN_INFO "ioremap returned %p\n", rawdataStart);
return 0;
}
void __exit map_cleanup(void)
{
printk("exit map module\n");
unregister_chrdev(MAP_MAJOR,"mapReserved");
if (rawdataStart != NULL) {
printk(KERN_INFO "Unmapping memory at %p\n", rawdataStart);
iounmap(rawdataStart);
} else {
printk(KERN_WARNING "No memory to unmap!\n");
}
return;
}
MODULE_LICENSE("GPL");
module_init( map_init);
module_exit( map_cleanup);
and my user space app is below
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#define RAW_DATA_SIZE 0x1E00000
int main(void)
{
void * data;
int fd = open("/dev/mapReserved", O_RDWR);
if (fd == -1) {
perror("open error...\n");
return -1;
}
data = mmap(NULL, RAW_DATA_SIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 4096);
close(fd);
return 0;
}
when i insert the module it's return
[ 873.621763] init map module
[ 873.623175] ioremap returned fb580000
but when i am executing the user space app it's return error
open error...
I've resolved this problem following those references :
1- Reserve memory in Linux driver module and share it using driver mmap
2- mmap of several GB of reserved memory using
in my case i am reserving 30M from the offset 2G and bellow is the code
module:
// #include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/mm.h>
#include <linux/kdev_t.h>
#include <asm/page.h>
#include <linux/cdev.h>
#include <linux/device.h>
#ifndef VM_RESERVED
# define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
#endif
#define RAW_DATA_SIZE 31457280
#define RAW_DATA_OFFSET 0x80000000UL
void *rawdataStart;
struct dentry *file;
/*
* Open the device; in fact, there's nothing to do here.
*/
int simple_open (struct inode *inode, struct file *filp)
{
return 0;
}
/*
* Closing is just as simpler.
*/
static int simple_release(struct inode *inode, struct file *filp)
{
return 0;
}
static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma)
{
int ret;
unsigned long mapoffset;
mapoffset = RAW_DATA_OFFSET + (vma->vm_pgoff << PAGE_SHIFT);
ret = remap_pfn_range(vma, vma->vm_start, mapoffset >> PAGE_SHIFT,
vma->vm_end - vma->vm_start, PAGE_SHARED);
if ( ret != 0 ) {
printk("Error remap_pfn_range. \n");
return -EAGAIN;
}
return 0;
}
/* Device uses remap_pfn_range */
static struct file_operations simple_remap_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.release = simple_release,
.mmap = simple_remap_mmap,
};
/*
* Module housekeeping.
*/
static int simple_init(void)
{
file = debugfs_create_file("mmap_example", 0644, NULL, NULL, &simple_remap_ops);
rawdataStart = ioremap(RAW_DATA_OFFSET, RAW_DATA_SIZE);
if (rawdataStart!=NULL){
printk("rawdataStart at:%p \n", rawdataStart);
memset(rawdataStart, 'c', 20971520);
memset(rawdataStart+20971520, '$', 100);
}else{
printk("rawdataStart is NULL \n");
return -1;
}
return 0;
}
static void simple_cleanup(void)
{
debugfs_remove(file);
if (rawdataStart != NULL) {
printk(KERN_INFO "Unmapping memory at %p\n", rawdataStart);
iounmap(rawdataStart);
} else {
printk(KERN_WARNING "No memory to unmap!\n");
}
}
module_init(simple_init);
module_exit(simple_cleanup);
MODULE_AUTHOR("Jonathan Corbet");
MODULE_LICENSE("Dual BSD/GPL");
and the user space App:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#define RAW_DATA_SIZE 31457280
int main(int argc, char **argv) {
int configfd;
char * address = NULL;
unsigned long chkSum;
FILE *fp = fopen("results.log", "w+");
configfd = open("/sys/kernel/debug/mmap_example", O_RDWR);
if (configfd < 0) {
perror("Open call failed");
return -1;
}
address = (unsigned char*) mmap(NULL, RAW_DATA_SIZE, PROT_WRITE,
MAP_PRIVATE, configfd, 0);
if (address == MAP_FAILED) {
perror("mmap operation failed");
return -1;
}
fputs(address, fp);
fclose(fp);
close(configfd);
return 0;
}
I referenced C code on this website: https://gist.github.com/austinmarton/2862515
Here is a image to explain:
I edit it at two parts, one pat is for ethertype(change 0x0800 to a custom-protocol 0x1234)
and another part is deleting code for IP header processing (because original code is based on IP, but I need a raw ethernet frame).
I used wireshark to detect packets, and I can receive the packets I sent(in left of image),and I can see send.out exactly sending packets(bottom right of image). But recv.out cannot receive packet !?(upper right of image).
However, if I use 0x0800 for protocol, recv.out can receive packets from outside, but still cannot receive the packets I sent.
Is there any mistake for setting socket
Here is my code:
send.c
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#define MY_DEST_MAC0 0xbc
#define MY_DEST_MAC1 0xee
#define MY_DEST_MAC2 0x7b
#define MY_DEST_MAC3 0x75
#define MY_DEST_MAC4 0x56
#define MY_DEST_MAC5 0x2a
#define DEFAULT_IF "eth0"
#define BUF_SIZ 1024
int main(int argc, char *argv[])
{
int sockfd;
struct ifreq if_idx;
struct ifreq if_mac;
int tx_len = 0;
char sendbuf[BUF_SIZ];
struct ether_header *eh = (struct ether_header *) sendbuf; /*structure*/
struct iphdr *iph = (struct iphdr *) (sendbuf + sizeof(struct ether_header));
struct sockaddr_ll socket_address;
char ifName[IFNAMSIZ];
unsigned short proto = 0x1234;
/* Get interface name *//*eth0*/
if (argc > 1)
strcpy(ifName, argv[1]);
else
strcpy(ifName, DEFAULT_IF);
/* Open RAW socket to send on *//*IPv4*/
if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(proto))) == -1) {
perror("socket");
}
/* Get the index of the interface to send on *//*0*/
memset(&if_idx, 0, sizeof(struct ifreq));
strncpy(if_idx.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFINDEX, &if_idx) < 0)/*save INDEX info into if_idx*/
perror("SIOCGIFINDEX");
/* Get the MAC address of the interface to send on *//*local*//*save MAC info into if_mac*/
memset(&if_mac, 0, sizeof(struct ifreq));
strncpy(if_mac.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFHWADDR, &if_mac) < 0)
perror("SIOCGIFHWADDR");
/* Construct the Ethernet header */
memset(sendbuf, 0, BUF_SIZ);
/* Ethernet header */
eh->ether_shost[0] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[0];
eh->ether_shost[1] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[1];
eh->ether_shost[2] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[2];
eh->ether_shost[3] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[3];
eh->ether_shost[4] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[4];
eh->ether_shost[5] = ((uint8_t *)&if_mac.ifr_hwaddr.sa_data)[5];
eh->ether_dhost[0] = MY_DEST_MAC0;
eh->ether_dhost[1] = MY_DEST_MAC1;
eh->ether_dhost[2] = MY_DEST_MAC2;
eh->ether_dhost[3] = MY_DEST_MAC3;
eh->ether_dhost[4] = MY_DEST_MAC4;
eh->ether_dhost[5] = MY_DEST_MAC5;
/* Ethertype field */
eh->ether_type = htons(proto);
tx_len += sizeof(struct ether_header);
/* Packet data */
sendbuf[tx_len++] = "h";
sendbuf[tx_len++] = "e";
sendbuf[tx_len++] = "l";
sendbuf[tx_len++] = "l";
sendbuf[tx_len++] = "o";
/* Index of the network device */
socket_address.sll_ifindex = if_idx.ifr_ifindex;
/* Address length*/
socket_address.sll_halen = ETH_ALEN;
/* Destination MAC */
socket_address.sll_addr[0] = MY_DEST_MAC0;
socket_address.sll_addr[1] = MY_DEST_MAC1;
socket_address.sll_addr[2] = MY_DEST_MAC2;
socket_address.sll_addr[3] = MY_DEST_MAC3;
socket_address.sll_addr[4] = MY_DEST_MAC4;
socket_address.sll_addr[5] = MY_DEST_MAC5;
/* Send packet */
int cnt=0;
while(cnt<5){
if (sendto(sockfd, sendbuf, tx_len, 0, (struct sockaddr*)&socket_address, sizeof(struct sockaddr_ll)) < 0)
printf("Send failed\n");
else
printf("success!\n");
cnt++;
}
return 0;
}
recv.c
#include <arpa/inet.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#define DEST_MAC0 0xbc
#define DEST_MAC1 0xee
#define DEST_MAC2 0x7b
#define DEST_MAC3 0x75
#define DEST_MAC4 0x56
#define DEST_MAC5 0x2a
#define ETHER_TYPE 0x1234
#define DEFAULT_IF "eth0"
#define BUF_SIZ 1024
int main(int argc, char *argv[])
{
char sender[INET6_ADDRSTRLEN];
int sockfd, ret, i;
int sockopt;
ssize_t numbytes;
struct ifreq ifopts; /* set promiscuous mode */
struct sockaddr_storage their_addr;
uint8_t buf[BUF_SIZ];
char ifName[IFNAMSIZ];
/* Get interface name *//*eth0*/
if (argc > 1)
strcpy(ifName, argv[1]);
else
strcpy(ifName, DEFAULT_IF);
/* Header structures */
struct ether_header *eh = (struct ether_header *) buf;
/* Open PF_PACKET socket, listening for EtherType ETHER_TYPE *//*0x1234*/
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
perror("listener: socket");
return -1;
}
/* Set interface to promiscuous mode - do we need to do this every time? *//*cpy ifname into ifr_name*/
strncpy(ifopts.ifr_name, ifName, IFNAMSIZ-1);
ioctl(sockfd, SIOCGIFFLAGS, &ifopts); /*set promisc mode*/
ifopts.ifr_flags |= IFF_PROMISC;
ioctl(sockfd, SIOCSIFFLAGS, &ifopts);
/* Allow the socket to be reused - incase connection is closed prematurely */
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof sockopt) == -1) {
perror("setsockopt");
close(sockfd);
exit(EXIT_FAILURE);
}
/* Bind to device */
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, IFNAMSIZ-1) == -1) {
perror("SO_BINDTODEVICE");
close(sockfd);
exit(EXIT_FAILURE);
}
repeat: printf("listener: Waiting to recvfrom...\n");
numbytes = recvfrom(sockfd, buf, BUF_SIZ, 0, NULL, NULL);
printf("listener: got packet %lu bytes\n", numbytes);
/* Check the packet is for me */
if (eh->ether_dhost[0] == DEST_MAC0 &&
eh->ether_dhost[1] == DEST_MAC1 &&
eh->ether_dhost[2] == DEST_MAC2 &&
eh->ether_dhost[3] == DEST_MAC3 &&
eh->ether_dhost[4] == DEST_MAC4 &&
eh->ether_dhost[5] == DEST_MAC5) {
printf("Correct destination MAC address\n");
} else {
printf("Wrong destination MAC: %x:%x:%x:%x:%x:%x\n",
eh->ether_dhost[0],
eh->ether_dhost[1],
eh->ether_dhost[2],
eh->ether_dhost[3],
eh->ether_dhost[4],
eh->ether_dhost[5]);
ret = -1;
goto done;
}
/* Print packet */
printf("\tData:");
for (i=0; i<numbytes; i++) printf("%02x:", buf[i]);
printf("\n");
done: goto repeat;
close(sockfd);
return ret;
}
you can get All frames from your target with below changes in your receive code :
please replace line :
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETHER_TYPE))) == -1) {
with this line :
if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
Because in your original code you changed normal ethernet header type then OS can not detect its process listener(your program) and get it to you but when you set this line, OS can get you all results so you can get your special answers.
I'm starting to do socket programming so someone should confirm this.
I'm pretty sure the interface will drop the packet because the source and destination mac are the same... try using another PC and change the destination mac on each side to confirm this (virtual machines work as well)
I have also used a similar code to transfer Ethernet frames. This type of socket does not work locally. As #Goncalo suggested use a different PC or if you have two NICs on your PC you should use them. Here is the Code I used to receive Frames.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <sys/ioctl.h>
union ethframe
{
struct
{
struct ethhdr header;
unsigned char data[ETH_DATA_LEN];
} field;
unsigned char buffer[ETH_FRAME_LEN];
};
int main(int argc, char **argv) {
char *iface = "eth1";
unsigned char dest[ETH_ALEN]
= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
unsigned short proto = 0x1234;
int recv_result,i;
char buff[ETH_FRAME_LEN];
unsigned short data_len;
int s;
if ((s = socket(AF_PACKET, SOCK_RAW, htons(proto))) < 0) {
printf("Error: could not open socket\n");
return -1;
}
struct ifreq buffer;
int ifindex;
memset(&buffer, 0x00, sizeof(buffer));
strncpy(buffer.ifr_name, iface, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &buffer) < 0) {
printf("Error: could not get interface index\n");
close(s);
return -1;
}
ifindex = buffer.ifr_ifindex;
unsigned char source[ETH_ALEN];
if (ioctl(s, SIOCGIFHWADDR, &buffer) < 0) {
printf("Error: could not get interface address\n");
close(s);
return -1;
}
memcpy((void*)source, (void*)(buffer.ifr_hwaddr.sa_data),
ETH_ALEN);
struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
socklen_t sll_len = (socklen_t)sizeof(saddrll);
if (recv_result = recvfrom(s, buff, ETH_FRAME_LEN, 0,
(struct sockaddr *)&saddrll, &sll_len) > 0)
printf("Success!\n");
else
printf("Error, could not send\n");
data_len=sizeof(buff);
printf("\tData:");
for (i=0; i<data_len; i++) printf("%c", buff[i]);
printf("\tDone: \n");
close(s);
return 0;
}
i installed the usb webcam driver in linux 2.6 version
then i want to capture using V4L please any one reply me how can i write the program to capture using webcam
I work with V4l using the reference of the linuxTV (http://linuxtv.org/downloads/v4l-dvb-apis/). They have the documentation about V4l and some examples. Take a look at the following example (i got from the linuxTV):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
#include "../libv4l/include/libv4l2.h"
#define CLEAR(x) memset(&(x), 0, sizeof(x))
struct buffer {
void *start;
size_t length;
};
static void xioctl(int fh, int request, void *arg)
{
int r;
do {
r = v4l2_ioctl(fh, request, arg);
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
if (r == -1) {
fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv)
{
struct v4l2_format fmt;
struct v4l2_buffer buf;
struct v4l2_requestbuffers req;
enum v4l2_buf_type type;
fd_set fds;
struct timeval tv;
int r, fd = -1;
unsigned int i, n_buffers;
char *dev_name = "/dev/video0";
char out_name[256];
FILE *fout;
struct buffer *buffers;
fd = v4l2_open(dev_name, O_RDWR | O_NONBLOCK, 0);
if (fd < 0) {
perror("Cannot open device");
exit(EXIT_FAILURE);
}
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 640;
fmt.fmt.pix.height = 480;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
xioctl(fd, VIDIOC_S_FMT, &fmt);
if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
exit(EXIT_FAILURE);
}
if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
printf("Warning: driver is sending image at %dx%d\n",
fmt.fmt.pix.width, fmt.fmt.pix.height);
CLEAR(req);
req.count = 2;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_REQBUFS, &req);
buffers = calloc(req.count, sizeof(*buffers));
for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = n_buffers;
xioctl(fd, VIDIOC_QUERYBUF, &buf);
buffers[n_buffers].length = buf.length;
buffers[n_buffers].start = v4l2_mmap(NULL, buf.length,
PROT_READ | PROT_WRITE, MAP_SHARED,
fd, buf.m.offset);
if (MAP_FAILED == buffers[n_buffers].start) {
perror("mmap");
exit(EXIT_FAILURE);
}
}
for (i = 0; i < n_buffers; ++i) {
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
xioctl(fd, VIDIOC_QBUF, &buf);
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
xioctl(fd, VIDIOC_STREAMON, &type);
for (i = 0; i < 20; i++) {
do {
FD_ZERO(&fds);
FD_SET(fd, &fds);
/* Timeout. */
tv.tv_sec = 2;
tv.tv_usec = 0;
r = select(fd + 1, &fds, NULL, NULL, &tv);
} while ((r == -1 && (errno = EINTR)));
if (r == -1) {
perror("select");
return errno;
}
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
xioctl(fd, VIDIOC_DQBUF, &buf);
sprintf(out_name, "out%03d.ppm", i);
fout = fopen(out_name, "w");
if (!fout) {
perror("Cannot open image");
exit(EXIT_FAILURE);
}
fprintf(fout, "P6\n%d %d 255\n",
fmt.fmt.pix.width, fmt.fmt.pix.height);
fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
fclose(fout);
xioctl(fd, VIDIOC_QBUF, &buf);
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
xioctl(fd, VIDIOC_STREAMOFF, &type);
for (i = 0; i < n_buffers; ++i)
v4l2_munmap(buffers[i].start, buffers[i].length);
v4l2_close(fd);
return 0;
}