ioctl in kernel module: why some commands are not executed? - linux-device-driver

I attach here my kernel module I developed and the test I am using at application level
memalloc.c
/*
* DMA memory allocation
* This kernel module allocates coherent, non-cached memory
* and returns the physical and virtual address of the allocated buffer
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/device.h>
#include <linux/cdev.h>
#include "memalloc.h"
#define DEVICE_NAME "memalloc"
// Max number of buffers
#define BUFFER_MAX_NUMBER 16
// Structure for buffer information
struct bufferInfo {
int active;
int size;
dma_addr_t handle;
int virtualAddress;
int *kernelAddress;
};
static struct bufferInfo bufferInfoTable[BUFFER_MAX_NUMBER];
// Defines which buffer is currently active - for mmap
static int activeBufferID;
struct memAllocIF {
struct device *device_p;
dev_t dev_node;
struct cdev cdev;
struct class *class_p;
};
static struct memAllocIF interface;
// Methods
static int releaseBuffer(int i)
{
if (i > BUFFER_MAX_NUMBER)
{
printk("Wrong bufferID %d\n", i);
return -1;
}
printk("Releasing buffer %d\n", i);
bufferInfoTable[i].active = 0;
dma_free_coherent(NULL, bufferInfoTable[i].size, bufferInfoTable[i].kernelAddress, bufferInfoTable[i].handle);
return 0;
}
static int reserveBuffer(size_t size)
{
int i;
for (i = 0; i < BUFFER_MAX_NUMBER; i++)
{
if (bufferInfoTable[i].active == 0)
{
printk("Reserving buffer %d\n", i);
bufferInfoTable[i].active = 1;
break;
}
}
if (i < BUFFER_MAX_NUMBER)
{
bufferInfoTable[i].kernelAddress = dma_alloc_coherent(NULL, size, &bufferInfoTable[i].handle, GFP_KERNEL);
if (bufferInfoTable[i].kernelAddress == NULL)
{
printk("Allocation failure\n");
return -1;
}
bufferInfoTable[i].size = (int)size;
return i;
}
else
{
printk("No buffer available\n");
return -1;
}
}
static void cleanup(void)
{
int i;
for (i = 0; i < BUFFER_MAX_NUMBER; i++)
{
if (bufferInfoTable[i].active != 0)
{
dma_free_coherent(NULL, bufferInfoTable[i].size, bufferInfoTable[i].kernelAddress, bufferInfoTable[i].handle);
bufferInfoTable[i].active = 0;
}
}
}
static unsigned int memAllocGetVirtual (int i)
{
if (i > BUFFER_MAX_NUMBER)
{
printk("Wrong bufferID %d\n", i);
return -1;
}
if (bufferInfoTable[i].active == 0)
{
printk("Inactive buffer - ID %d\n", i);
return -1;
}
printk("request for buffer %d: vaddr = %X\n", i, (unsigned int)bufferInfoTable[i].virtualAddress);
return bufferInfoTable[i].virtualAddress;
}
static unsigned int memAllocGetPhysical (int i)
{
if (i > BUFFER_MAX_NUMBER)
{
printk("Wrong bufferID %d\n", i);
return -1;
}
return (unsigned int)bufferInfoTable[i].handle;
}
static long memAllocIoctl (struct file *fd, unsigned int cmd, unsigned long arg)
{
printk("received command %u arg %lu\n", cmd, arg);
switch(cmd)
{
case MEMALLOC_RESERVE:
return reserveBuffer(arg);
break;
case MEMALLOC_RELEASE:
return releaseBuffer(arg);
break;
case MEMALLOC_GET_VIRTUAL:
return memAllocGetVirtual(arg);
break;
case MEMALLOC_GET_PHYSICAL:
return memAllocGetPhysical(arg);
break;
case MEMALLOC_ACTIVATE_BUFFER:
if (arg > BUFFER_MAX_NUMBER || bufferInfoTable[arg].active == 0)
{
printk("Wrong bufferID %lu\n", arg);
return -1;
}
activeBufferID = arg;
return arg;
break;
default:
printk("Wrong command: %d\n", cmd);
return -1;
break;
}
}
static int memAllocMmap (struct file *fd, struct vm_area_struct *vma)
{
bufferInfoTable[activeBufferID].virtualAddress = dma_common_mmap(interface.device_p, vma, bufferInfoTable[activeBufferID].kernelAddress, bufferInfoTable[activeBufferID].handle, vma->vm_end-vma->vm_start);
printk("mmap for idx %d: vaddr = %X\n", activeBufferID, (int)bufferInfoTable[activeBufferID].virtualAddress);
return bufferInfoTable[activeBufferID].virtualAddress;
}
static int memAllocRelease(struct inode *in, struct file *fd)
{
cleanup();
return 0;
}
static int memAllocOpen(struct inode *ino, struct file *file)
{
file->private_data = container_of(ino->i_cdev, struct memAllocIF, cdev);
return 0;
}
static struct file_operations fops = {
.unlocked_ioctl = memAllocIoctl,
.mmap = memAllocMmap,
.release = memAllocRelease,
.open = memAllocOpen
};
static int __init memAllocInit(void)
{
int rc;
int i;
static struct class *local_class_p = NULL;
printk("Loading DMA allocation module\n");
// Allocate a character device from the kernel for this driver
rc = alloc_chrdev_region(&interface.dev_node, 0, 1, DEVICE_NAME);
if (rc)
{
printk("Unable to get a char device number\n");
return rc;
}
// Initialize the ter device data structure before registering the character device with the kernel
cdev_init(&interface.cdev, &fops);
rc = cdev_add(&interface.cdev, interface.dev_node, 1);
if (rc)
{
printk("Unable to add char device\n");
cdev_del(&interface.cdev);
return rc;
}
// Create the device in sysfs which will allow the device node in /dev to be created
local_class_p = class_create(THIS_MODULE, DEVICE_NAME);
interface.class_p = local_class_p;
// Create the device node in /dev so the device is accessible as a character device
interface.device_p = device_create(interface.class_p, NULL, interface.dev_node, NULL, DEVICE_NAME);
if (IS_ERR(interface.device_p))
{
printk("Unable to create the device\n");
class_destroy(interface.class_p);
cdev_del(&interface.cdev);
return rc;
}
for (i = 0; i < BUFFER_MAX_NUMBER; i++)
{
bufferInfoTable[activeBufferID].active = 0;
}
return 0;
}
static void __exit my_memAllocExit(void)
{
printk("Module unloading\n");
cleanup();
cdev_del(&interface.cdev);
device_destroy(interface.class_p, interface.dev_node);
class_destroy(interface.class_p);
unregister_chrdev_region(interface.dev_node, 1);
}
module_init(memAllocInit);
module_exit(my_memAllocExit);
MODULE_AUTHOR("me");
MODULE_DESCRIPTION("Create a buffer and return physical and virtual address, for DMA userspace driver");
MODULE_LICENSE("GPL");
memalloc.h
#ifndef MEMALLOC_H
#define MEMALLOC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <linux/types.h>
#include <asm/ioctl.h>
static long memAllocIoctl (struct file *, unsigned int, unsigned long);
static int memAllocMmap (struct file *, struct vm_area_struct *);
static int memAllocRelease (struct inode *, struct file *);
static int memAllocOpen(struct inode *, struct file *);
enum memAllocCmd
{
MEMALLOC_RESERVE = 0,
MEMALLOC_RELEASE = 1,
MEMALLOC_GET_VIRTUAL = 2,
MEMALLOC_GET_PHYSICAL = 3,
MEMALLOC_ACTIVATE_BUFFER = 4,
};
#ifdef __cplusplus
}
#endif
#endif /* MEMALLOC_H */
test.c
#include <stdlib.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
// derive this from memalloc.h
enum memAllocCmd
{
MEMALLOC_RESERVE = 0,
MEMALLOC_RELEASE = 1,
MEMALLOC_GET_VIRTUAL = 2,
MEMALLOC_GET_PHYSICAL = 3,
MEMALLOC_ACTIVATE_BUFFER = 4,
};
int main ()
{
int memAllocFd;
volatile int iVaddr;
volatile int oVaddr;
volatile int iVaddr_2;
volatile int oVaddr_2;
volatile void * iPaddr;
volatile void * oPaddr;
int iBufID;
int oBufID;
int size = 2048;
memAllocFd = open("/dev/memalloc", O_RDWR);
// create iBuffer
iBufID = ioctl(memAllocFd, MEMALLOC_RESERVE, size);
iPaddr = (void *)ioctl(memAllocFd, MEMALLOC_GET_PHYSICAL, iBufID);
ioctl(memAllocFd, MEMALLOC_ACTIVATE_BUFFER, iBufID);
iVaddr = (int)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, memAllocFd, 0);
ioctl(memAllocFd, MEMALLOC_GET_VIRTUAL, iBufID);
/*
if (iVaddr != iVaddr_2)
{
printf("Error: virtual addresses for buffer %d don't match: %X %X\n", iBufID, iVaddr, iVaddr_2);
}
*/
// create oBuffer
oBufID = ioctl(memAllocFd, MEMALLOC_RESERVE, size);
oPaddr = (void *)ioctl(memAllocFd, MEMALLOC_GET_PHYSICAL, oBufID);
ioctl(memAllocFd, MEMALLOC_ACTIVATE_BUFFER, oBufID);
oVaddr = (int)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, memAllocFd, 0);
ioctl(memAllocFd, MEMALLOC_GET_VIRTUAL, oBufID);
/*
if (oVaddr != oVaddr_2)
{
printf("Error: virtual addresses for buffer %d don't match: %X %X\n", oBufID, oVaddr, oVaddr_2);
}
*/
ioctl(memAllocFd, MEMALLOC_RELEASE, iBufID);
ioctl(memAllocFd, MEMALLOC_RELEASE, oBufID);
return 0;
}
Result of the test is
received command 0 arg 2048
Reserving buffer 0
received command 3 arg 0
received command 4 arg 0
mmap for idx 0: vaddr = 0
received command 0 arg 2048
Reserving buffer 1
received command 3 arg 1
received command 4 arg 1
mmap for idx 1: vaddr = 0
received command 1 arg 0
Releasing buffer 0
received command 1 arg 1
Releasing buffer 1
Which means that all ioctl calls with arg=MEMALLOC_GET_VIRTUAL are not executed, while all the others are.
What can be the reason for that?
Thanks,
Max

Related

WL_SHM_FORMAT_ARGB8888 not fully transparent if color bit was set

I am learning Wayland client programming and now I'm trying to make transparent surface.
I created a buffer and paint each pixels to shared memory. I am using WL_SHM_FORMAT_ARGB8888 format but it is not working as I expected.
As I understand, 0x00ff0000 means 255 red, 0 green, 0 blue and 0 alpha so the pixel should not shown. But it shows semi-transparent red surface to me.
Below is entire source code working on Weston compositor.
// main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <errno.h>
#include <unistd.h>
#include "xdg-shell.h"
struct wl_display *display = NULL;
struct wl_compositor *compositor = NULL;
struct wl_surface *surface;
struct zxdg_shell_v6 *xdg_shell = NULL;
struct zxdg_surface_v6 *xdg_surface;
struct zxdg_toplevel_v6 *xdg_toplevel;
struct wl_shm *shm;
struct wl_buffer *buffer;
void *shm_data;
int WIDTH = 480;
int HEIGHT = 360;
//===============
// Xdg
//===============
static void xdg_shell_ping_handler(void *data, struct zxdg_shell_v6 *xdg_shell,
uint32_t serial)
{
zxdg_shell_v6_pong(xdg_shell, serial);
printf("ping pong!\n");
}
static const struct zxdg_shell_v6_listener xdg_shell_listener = {
.ping = xdg_shell_ping_handler,
};
static void xdg_toplevel_configure_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel, int32_t width, int32_t height,
struct wl_array *states)
{
printf("Configure: %dx%d\n", width, height);
}
static void xdg_toplevel_close_handler(void *data,
struct zxdg_toplevel_v6 *xdg_toplevel)
{
printf("Close\n");
}
static const struct zxdg_toplevel_v6_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure_handler,
.close = xdg_toplevel_close_handler,
};
static void xdg_surface_configure_handler(void *data,
struct zxdg_surface_v6 *xdg_surface, uint32_t serial)
{
fprintf(stderr, "xdg_surface_configure_handler().\n");
zxdg_surface_v6_ack_configure(xdg_surface, serial);
}
static const struct zxdg_surface_v6_listener xdg_surface_listener = {
.configure = xdg_surface_configure_handler,
};
//=================
// File system
//=================
static int set_cloexec_or_close(int fd)
{
long flags;
if (fd == -1) {
return -1;
}
flags = fcntl(fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
return fd;
err:
close(fd);
return -1;
}
static int create_tmpfile_cloexec(char *tmpname)
{
int fd;
#ifdef HAVE_MKOSTEMP
fd= mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0) {
unlink(tmpname);
}
#else
fd = mkstemp(tmpname);
if (fd >= 0) {
fd = set_cloexec_or_close(fd);
unlink(tmpname);
}
#endif
return fd;
}
int os_create_anonymous_file(off_t size)
{
static const char template[] = "/blusher-shared-XXXXXX";
const char *path;
char *name;
int fd;
path = getenv("XDG_RUNTIME_DIR");
if (!path) {
errno = ENOENT;
return -1;
}
name = malloc(strlen(path) + sizeof(template));
if (!name) {
return -1;
}
strcpy(name, path);
strcat(name, template);
fd = create_tmpfile_cloexec(name);
free(name);
if (fd < 0) {
return -1;
}
if (ftruncate(fd, size) < 0) {
close(fd);
return -1;
}
return fd;
}
//==============
// Painting
//==============
static void paint_pixels()
{
uint32_t *pixel = shm_data;
fprintf(stderr, "Painting pixels.\n");
for (int n = 0; n < WIDTH * HEIGHT; ++n) {
if (n > 1100 && n < 1200) {
pixel[n] = 0xffff0000; // please ignore this
} else {
pixel[n] = 0x00ff0000;
}
}
}
static struct wl_buffer* create_buffer()
{
struct wl_shm_pool *pool;
int stride = WIDTH * 4; // 4 bytes per pixel
int size = stride * HEIGHT;
int fd;
struct wl_buffer *buff;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "Creating a buffer file for %d B filed: %m\n",
size);
exit(1);
}
shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED) {
fprintf(stderr, "mmap filed: %m\n");
close(fd);
exit(1);
}
pool = wl_shm_create_pool(shm, fd, size);
buff = wl_shm_pool_create_buffer(
pool,
0,
WIDTH,
HEIGHT,
stride,
WL_SHM_FORMAT_ARGB8888
);
wl_shm_pool_destroy(pool);
return buff;
}
static void create_window()
{
buffer = create_buffer();
wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_damage(surface, 0, 0, WIDTH, HEIGHT);
wl_surface_commit(surface);
}
static void shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
// struct display *d = data;
// d->formats |= (1 << format);
fprintf(stderr, "Format %d\n", format);
}
struct wl_shm_listener shm_listener = {
shm_format,
};
//==============
// Global
//==============
static void global_registry_handler(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
if (strcmp(interface, "wl_compositor") == 0) {
fprintf(stderr, "Interface is <wl_compositor>.\n");
compositor = wl_registry_bind(
registry,
id,
&wl_compositor_interface,
version
);
} else if (strcmp(interface, "zxdg_shell_v6") == 0) {
fprintf(stderr, "Interface is <zxdg_shell_v6>.\n");
xdg_shell = wl_registry_bind(registry, id, &zxdg_shell_v6_interface, 1);
} else if (strcmp(interface, "wl_shm") == 0) {
fprintf(stderr, "Interface is <wl_shm>.\n");
shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
wl_shm_add_listener(shm, &shm_listener, NULL);
} else {
// printf("(%d) Got a registry event for <%s> id <%d>\n",
// version, interface, id);
}
}
static void global_registry_remover(void *data, struct wl_registry *registry,
uint32_t id)
{
printf("Got a registry losing event for <%d>\n", id);
}
static const struct wl_registry_listener registry_listener = {
global_registry_handler,
global_registry_remover
};
//==============
// Main
//==============
int main(int argc, char *argv[])
{
(void)argc;
(void)argv;
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "Can't connect to display.\n");
exit(1);
}
printf("Connected to display.\n");
struct wl_registry *registry = wl_display_get_registry(display);
wl_registry_add_listener(registry, &registry_listener, NULL);
wl_display_dispatch(display);
// wl_display_roundtrip(display);
// Check compositor.
fprintf(stderr, " - Checking compositor...\n");
if (compositor == NULL) {
fprintf(stderr, "Can't find compositor.\n");
exit(1);
}
// Check surface.
fprintf(stderr, " - Checking surface...\n");
surface = wl_compositor_create_surface(compositor);
if (surface == NULL) {
fprintf(stderr, "Can't create surface.\n");
exit(1);
}
if (xdg_shell == NULL) {
fprintf(stderr, "Haven't got a Xdg shell.\n");
exit(1);
}
zxdg_shell_v6_add_listener(xdg_shell, &xdg_shell_listener, NULL);
// Check shell surface.
xdg_surface =
zxdg_shell_v6_get_xdg_surface(xdg_shell, surface);
zxdg_surface_v6_add_listener(xdg_surface, &xdg_surface_listener, NULL);
xdg_toplevel = zxdg_surface_v6_get_toplevel(xdg_surface);
zxdg_toplevel_v6_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL);
// Signal that the surface is ready to be configured.
wl_surface_commit(surface);
// Wait for the surface to be configured.
wl_display_roundtrip(display);
create_window();
paint_pixels();
// wl_surface_attach(surface, buffer, 0, 0);
// wl_surface_commit(surface);
while (wl_display_dispatch(display) != -1) {
;
}
wl_display_disconnect(display);
printf("Disconnected from display.\n");
return 0;
}
# Makefile
default:
wayland-scanner client-header /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.h
wayland-scanner public-code /usr/share/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml xdg-shell.c
gcc -lwayland-client -lwayland-egl -lEGL -lGLESv2 main.c xdg-shell.c
But when I set pixel to 0x00000000, then it is fully transparent.
And in some tests, subsurfaces are completely transparent even there are color bits set. I want to know what is prevent the transparent toplevel surface with color bits.
If your wayland compositor supports alpha-compositing-v1 protocol you can use it do what you want.
In short; get a reference to zwp_alpha_compositing_v1 struct in you registry handler then after creating your surface you set it like this:
struct zwp_blending_v1* blending = zwp_alpha_compositing_v1_get_blending(<YOUR_ZWP_ALPHA_COMPOSITING>, <YOUR_WL_SURFACE>);
zwp_blending_v1_set_blending(blending, ZWP_BLENDING_V1_BLENDING_EQUATION_STRAIGHT);
This is an equivalent to (src_alpha, one_minus_src_alpha) blending.

How to return to menu in Socket Client-Server

I've writen this code but it doesn't work correctly.
This is menu interface:
*************ENCODE_DECODE_BASE64**************
******* 1. Encode ********
******* 2. Decode ********
******* 3. Exit ********
***********************************************
When i choose 1, "Encode". The function runs but the process exits.
I want when I choose 1, the function to run and then after that, the menu to display again.
Can you help me?
Here is Clientcode:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#define MAX 1024
// read filename
char *inputString(int size){
int test=0;
char *s=(char*)malloc(size);
do{
if(test!=0){
printf("File not found !!!!!!");
}
fgets(s,size,stdin);
test++;
}while(strlen(s)<=1);
return strtok(s,"\n");
}
int main(int argc, char *argv[]){
int sockfd;
struct sockaddr serverAddr; //server address
char buff[1024];
struct sockaddr_in inAddr;
long int sentBytes,revedBytes;
sockfd=socket(AF_INET,SOCK_STREAM,0); // create socket
if (sockfd == -1)
{
printf("ERROR opening socket\n");
return 1;
}
printf("Socket done\n");
inAddr.sin_family=AF_INET; //default
inAddr.sin_port=htons(5500); // service port
inet_aton("127.0.0.1",&inAddr.sin_addr);
//connectting
if(connect(sockfd,(struct sockaddr *)&inAddr,sizeof(struct sockaddr))<0){
printf("Connect failed.\n");
return 1;
}
printf("Connection accepted\n");
char *FileName; // file input
char *Result; // file return
int choice;
do{
printf("\n*************ENCODE_DECODE_BASE64**************");
printf("\n******* 1. Encode ********");
printf("\n******* 2. Decode ********");
printf("\n******* 3. Exit ********");
printf("\n***********************************************\n");
printf("Choice: ");
choice = getchar();
while(getchar() !='\n');
switch(choice)
{
case '1':
//demo encode////////////////////////////////////////
send(sockfd,"encode",5,0); // send to server when choose 1
printf("File Encode : ");
FileName = inputString(20);
FILE *fpt = fopen(FileName,"r");
if(fpt==NULL){
printf("File not found");
return -1;
}
printf("File Result: ");
Result = inputString(20);
FILE *ft = fopen(Result,"w");
while(!feof(fpt)){
if (fgets(buff,MAX,fpt) != NULL ){
sentBytes=send(sockfd,buff,1024,0);
revedBytes=recv(sockfd,buff,1024,0);
fprintf(ft,"%s\n",buff);
}
}
printf("Encode done!thanks you !\n");
//close(sockfd);
fclose(fpt);fclose(ft);
return 0;
break;
//decode ///////////////////////////////////////////////
case '2':
send(sockfd,"decode",6,0);
printf("File Decode : ");
FileName = inputString(20);
FILE *fpt1 = fopen(FileName,"r");
if(fpt1==NULL){
printf("File not found");
return -1;
}
printf("File Result : ");
Result = inputString(20);
FILE *ft1 = fopen(Result,"w");
while(!feof(fpt1)){
if (fgets(buff,MAX,fpt1) != NULL ){
sentBytes=send(sockfd,buff,1024,0);
revedBytes=recv(sockfd,buff,1024,0);
fprintf(ft1,"%s",buff);
}
}
printf("Decode done ! thanks you !\n");
//close(sockfd);
fclose(fpt1);fclose(ft1);
return 0;
break;
///////////////////////////////////////////////////////
case '3':
printf("Thanks!\n");
break;
default: printf("wrong number, please try again!\n"); break;
//end choice///////////////////////////////////////
}
}while(choice!='3');
//end menu
//close(sockfd);
//return 0;
}
and here is ServerCode:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
void b64_decode(char *b64src, char *clrdst) {
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break;
}
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0;
}
}
i++;
}
}
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
}
/* encode - base64 encode a stream, adding padding if needed */
void b64_encode(char *clrstr, char *b64dst) {
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++;
}
else in[i] = 0;
}
if( len ) {
encodeblock( in, b64dst, len );
}
}
}
void sig_chld(int signo) //child
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG))>0)
printf("child %d terminated\n", pid);
return;
}
int main()
{
int listen_sock, conn_sock;
int server_len, client_len,choice;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
char myb64[1024] = ""; //encode
char mydst[1024] = ""; //decode
int sentBytes,revedBytes,bytes_readi;
char buff[1024]; //buffer to send data
listen_sock = socket(AF_INET, SOCK_STREAM, 0); //create socket
if (listen_sock == -1)
{
printf("ERROR opening socket\n");
return 0;
}
printf("Socket done\n");
//Thiet lap dia chi server
server_address.sin_family = AF_INET; //default
inet_aton("127.0.0.1",&server_address.sin_addr); //ip server
server_address.sin_port = htons(5500); // port server
server_len = sizeof(server_address);
if(bind(listen_sock, (struct sockaddr *)&server_address,server_len)<0)
{
printf("ERROR on binding\n");
return 0;
}
printf("Bind done\n");
int check = listen(listen_sock,10);
if (check == -1)
{
printf("Error connect");
return 0;
}
printf("Waiting connect..\n");
while(1) {
client_len = sizeof(client_address);
conn_sock = accept(listen_sock,(struct sockaddr *)&client_address, &client_len);
if(conn_sock==-1){
printf("Error connect\n");
return 1;
}else{
printf("Accept new connection\n");
}
if(fork() == 0){
close(listen_sock);
do{
revedBytes = recv(conn_sock,buff,1024,0);
buff[revedBytes]='\0';
if(strcmp(buff,"mahoa")==0) choice=1;
else if(strcmp(buff,"giaima")==0) choice=2; else choice = 3;
switch(choice)
{
case 1:
while((revedBytes = recv(conn_sock,buff,1024,0)) > 0){
buff[revedBytes]='\0';
//printf("string send by client encode : %s\n",buff);
b64_encode(buff, myb64); //ma hoa
sentBytes=send(conn_sock,myb64,1024,0); //gui lai string da ma hoa cho client
}
close(conn_sock);//Dong ket noi cua client
exit(0);
break;
case 2:
while((revedBytes = recv(conn_sock,buff,1024,0)) > 0){
buff[revedBytes]='\0';
//printf("string send by client decode: %s\n",buff);
b64_decode(buff,mydst); // giaima
sentBytes=send(conn_sock,mydst,1024,0);
}
close(conn_sock);
exit(0);
break;
case 3:break;
}
}while(choice!=3);
break;
}
signal(SIGCHLD,sig_chld);
close(conn_sock);
}
return 1;
}

how to write v4L capturing program for usb web cam (640x480)

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;
}

Linux SPI driver crasj

I am trying to write a SPI driver for Angstrom Linux 2.6.36 for Gumstix Overo Fire. My driver keeps on crashing in the interrupt handler. Here is the full code
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/cdev.h>
#include <linux/spi/spi.h>
#include <linux/string.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <mach/gpio.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include <linux/hrtimer.h>
#define IRQ_PIN 10
#define SPI_BUFF_SIZE 4
#define USER_BUFF_SIZE 128
#define SPI_BUS 1
#define SPI_BUS_CS1 1
#define SPI_BUS_SPEED 1500000
unsigned char *buff_even = 0;
unsigned char *buff_odd = 0;
unsigned char *temp_buff = 0;
unsigned int sample_counter = 0;
unsigned int buff_counter = 0;
unsigned int current_buffer = 0;
unsigned int local_current_buffer = 0;
unsigned int local_sample_counter = 0;
unsigned int num_reads = 0;
unsigned int num_miss_samples = 0;
unsigned int regval = 0;
#define LIMIT (4000)
#define BUFF_SIZE (4*LIMIT)
#define MAJOR_NUM 100
#define READ_CURR_COUNTER _IOWR(MAJOR_NUM, 1, int)
#define READ_BUFF _IOWR(MAJOR_NUM, 2, int)
#define READ_CURR_BUFF_NO _IOWR(MAJOR_NUM, 3, int)
#define READ_REGISTER _IOWR(MAJOR_NUM, 4, unsigned char)
#define WRITE_REGISTER _IOWR(MAJOR_NUM, 5, int)
#define START_READ _IOWR(MAJOR_NUM, 6, int)
#define STOP_READ _IOWR(MAJOR_NUM, 7, int)
const char this_driver_name[] = "adc";
static int running = 0;
static int resetting = 0;
static int reading = 0;
struct spike_control
{
struct spi_message msg;
struct spi_transfer transfer;
u8 *tx_buff;
u8 *rx_buff;
};
static struct spike_control spike_ctl;
struct spike_dev
{
struct semaphore spi_sem;
struct semaphore fop_sem;
dev_t devt;
struct cdev cdev;
struct class *class;
struct spi_device *spi_device;
char *user_buff;
u8 test_data;
int irq;
};
static struct spike_dev spike_dev;
static DEFINE_MUTEX(list_lock);
static DEFINE_MUTEX(count_lock);
static int status;
static void spike_completion_handler(void *arg)
{
local_sample_counter++;
if (sample_counter >= local_sample_counter + 1)
num_miss_samples++;
if (current_buffer == 0)
{
buff_even[buff_counter++] = spike_ctl.rx_buff[0];
buff_even[buff_counter++] = spike_ctl.rx_buff[1];
buff_even[buff_counter++] = spike_ctl.rx_buff[2];
buff_even[buff_counter++] = spike_ctl.rx_buff[3];
}
else if (current_buffer == 1)
{
buff_odd[buff_counter++] = spike_ctl.rx_buff[0];
buff_odd[buff_counter++] = spike_ctl.rx_buff[1];
buff_odd[buff_counter++] = spike_ctl.rx_buff[2];
buff_odd[buff_counter++] = spike_ctl.rx_buff[3];
}
memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE);
if (sample_counter == LIMIT)
{
buff_counter = 0;
mutex_lock(&count_lock);
if (current_buffer == 0)
current_buffer = 1;
else
current_buffer = 0;
sample_counter = 0;
mutex_unlock(&count_lock);
local_sample_counter = 0;
}
}
static irqreturn_t adc_handler(int irq, void *dev_id)
{
sample_counter++;
spi_message_init(&spike_ctl.msg);
spike_ctl.msg.complete = spike_completion_handler;
spike_ctl.msg.context = NULL;
spike_ctl.transfer.tx_buf = NULL;
spike_ctl.transfer.rx_buf = spike_ctl.rx_buff;
spike_ctl.transfer.len = 4;
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_async(spike_dev.spi_device, &spike_ctl.msg);
return IRQ_HANDLED;
}
static void resetbuffers(void)
{
local_sample_counter = 0;
sample_counter = 0;
num_miss_samples = 0;
current_buffer = 0;
buff_counter = 0;
memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE);
memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE);
memset(buff_even, 0, BUFF_SIZE);
memset(buff_odd, 0, BUFF_SIZE);
memset(temp_buff, 0, BUFF_SIZE);
}
static int read_register(unsigned char addr)
{
if (down_interruptible(&spike_dev.spi_sem))
return -ERESTARTSYS;
if (!spike_dev.spi_device)
{
up(&spike_dev.spi_sem);
return -ENODEV;
}
memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE);
memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE);
spike_ctl.transfer.tx_buf = spike_ctl.tx_buff;
spike_ctl.transfer.rx_buf = spike_ctl.rx_buff;
spike_ctl.transfer.len = 1;
spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP1:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP1\n\t");
spike_ctl.tx_buff[0] = 0x20 + addr;//Address of register
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP2:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP2\n\t");
spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP3:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP3\n\t");
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP4:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP4\n\t");
printk(KERN_ALERT "%x\n",spike_ctl.rx_buff[0]);
regval = spike_ctl.rx_buff[0];
// spike_ctl.tx_buff[0] = 0x10;//Start read data continuous
// spi_message_init(&spike_ctl.msg);
// spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
// status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
up(&spike_dev.spi_sem);
return status;
}
static int write_register(unsigned char addr, unsigned char val)
{
if (down_interruptible(&spike_dev.spi_sem))
return -ERESTARTSYS;
if (!spike_dev.spi_device)
{
up(&spike_dev.spi_sem);
return -ENODEV;
}
memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE);
memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE);
spike_ctl.transfer.tx_buf = spike_ctl.tx_buff;
spike_ctl.transfer.rx_buf = spike_ctl.rx_buff;
spike_ctl.transfer.len = 1;
spike_ctl.tx_buff[0] = 0x11;//Stop read data continuous
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP5:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP5\n\t");
spike_ctl.tx_buff[0] = 0x40 + addr;//Address of register
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP6:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP6\n\t");
spike_ctl.tx_buff[0] = 0;//Number of registers to read minus 1
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP7:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP7\n\t");
spike_ctl.tx_buff[0] = val;//Value to write
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
__asm__ __volatile__("ldr r0,=0x2710\n\t"
".LOOP8:\n\t"
"subs r0,r0,#1\n\t"
"bne .LOOP8\n\t");
spike_ctl.tx_buff[0] = 0x10;//Start read data continuous
spi_message_init(&spike_ctl.msg);
spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
// spike_ctl.tx_buff[0] = 0x10;//Start read data continuous
// spi_message_init(&spike_ctl.msg);
// spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg);
// status = spi_sync(spike_dev.spi_device, &spike_ctl.msg);
up(&spike_dev.spi_sem);
return status;
}
static long adc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned char addr;
switch(cmd)
{
case READ_CURR_COUNTER:
mutex_lock(&count_lock);
local_current_buffer = current_buffer;
local_sample_counter = sample_counter;
mutex_unlock(&count_lock);
copy_to_user((void *)arg, &local_sample_counter, sizeof(unsigned int));
printk(KERN_ALERT "Read current counter %d\n",local_sample_counter);
break;
case READ_BUFF:
mutex_lock(&count_lock);
local_current_buffer = current_buffer;
local_sample_counter = sample_counter;
mutex_unlock(&count_lock);
if (local_current_buffer == 0)
{
memcpy(temp_buff,buff_odd, BUFF_SIZE);
// memset(temp_buff, 'Q', BUFF_SIZE);
}
else
{
memcpy(temp_buff,buff_even, BUFF_SIZE);
// memset(temp_buff, 'T', BUFF_SIZE);
}
copy_to_user((void *)arg, temp_buff, BUFF_SIZE);
num_reads++;
break;
case READ_CURR_BUFF_NO:
mutex_lock(&count_lock);
local_current_buffer = current_buffer;
local_sample_counter = sample_counter;
mutex_unlock(&count_lock);
copy_to_user((void *)arg, &local_current_buffer, sizeof(int));
break;
case READ_REGISTER:
get_user(addr, (unsigned char *)arg);
disable_irq(spike_dev.irq);
read_register(addr);
enable_irq(spike_dev.irq);
copy_to_user((void *)arg, &regval, sizeof(int));
break;
case WRITE_REGISTER:
disable_irq(spike_dev.irq);
enable_irq(spike_dev.irq);
//copy_to_user((void *)arg, &local_current_buffer, sizeof(int));
break;
default:
return -ENOTTY;
}
return 1;
}
static int spike_open(struct inode *inode, struct file *filp)
{
int status = 0;
if (down_interruptible(&spike_dev.fop_sem))
return -ERESTARTSYS;
if (!spike_dev.user_buff) {
spike_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL);
if (!spike_dev.user_buff)
status = -ENOMEM;
}
up(&spike_dev.fop_sem);
return status;
}
static int spike_probe(struct spi_device *spi_device)
{
if (down_interruptible(&spike_dev.spi_sem))
return -EBUSY;
spike_dev.spi_device = spi_device;
printk(KERN_ALERT "SPI[%d] max_speed_hz %d Hz\n", spi_device->chip_select, spi_device->max_speed_hz);
up(&spike_dev.spi_sem);
return 0;
}
static int spike_remove(struct spi_device *spi_device)
{
if (down_interruptible(&spike_dev.spi_sem))
return -EBUSY;
spike_dev.spi_device = NULL;
up(&spike_dev.spi_sem);
return 0;
}
static int __init add_spike_device_to_bus(void)
{
struct spi_master *spi_master;
struct spi_device *spi_device;
struct device *pdev;
char buff[64];
int status = 0;
spi_master = spi_busnum_to_master(SPI_BUS);
if (!spi_master)
{
printk(KERN_ALERT "spi_busnum_to_master(%d) returned NULL\n",
SPI_BUS);
printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n");
return -1;
}
spi_device = spi_alloc_device(spi_master);
if (!spi_device)
{
put_device(&spi_master->dev);
printk(KERN_ALERT "spi_alloc_device() failed\n");
return -1;
}
spi_device->chip_select = SPI_BUS_CS1;
/* Check whether this SPI bus.cs is already claimed */
snprintf(buff, sizeof(buff), "%s.%u",
dev_name(&spi_device->master->dev),
spi_device->chip_select);
pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff);
if (pdev)
{
/* We are not going to use this spi_device, so free it */
spi_dev_put(spi_device);
/*
* There is already a device configured for this bus.cs
* It is okay if it us, otherwise complain and fail.
*/
if (pdev->driver && pdev->driver->name && strcmp(this_driver_name, pdev->driver->name))
{
printk(KERN_ALERT
"Driver [%s] already registered for %s\n",
pdev->driver->name, buff);
status = -1;
}
}
else
{
spi_device->max_speed_hz = SPI_BUS_SPEED;
spi_device->mode = SPI_MODE_0;
spi_device->bits_per_word = 8;
spi_device->irq = -1;
spi_device->controller_state = NULL;
spi_device->controller_data = NULL;
strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE);
status = spi_add_device(spi_device);
if (status < 0)
{
spi_dev_put(spi_device);
printk(KERN_ALERT "spi_add_device() failed: %d\n",
status);
}
}
put_device(&spi_master->dev);
return status;
}
static struct spi_driver spike_driver = {
.driver = {
.name = this_driver_name,
.owner = THIS_MODULE,
},
.probe = spike_probe,
.remove = __devexit_p(spike_remove),
};
static int __init spike_init_spi(void)
{
int error;
spike_ctl.tx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA);
if (!spike_ctl.tx_buff)
{
error = -ENOMEM;
goto spike_init_error;
}
spike_ctl.rx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA);
if (!spike_ctl.rx_buff)
{
error = -ENOMEM;
goto spike_init_error;
}
error = spi_register_driver(&spike_driver);
if (error < 0)
{
printk(KERN_ALERT "spi_register_driver() failed %d\n", error);
goto spike_init_error;
}
error = add_spike_device_to_bus();
if (error < 0)
{
printk(KERN_ALERT "add_spike_to_bus() failed\n");
spi_unregister_driver(&spike_driver);
goto spike_init_error;
}
spike_dev.irq = OMAP_GPIO_IRQ(IRQ_PIN);
return 0;
spike_init_error:
if (spike_ctl.tx_buff) {
kfree(spike_ctl.tx_buff);
spike_ctl.tx_buff = 0;
}
if (spike_ctl.rx_buff) {
kfree(spike_ctl.rx_buff);
spike_ctl.rx_buff = 0;
}
return error;
}
static ssize_t spike_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
size_t len;
ssize_t status = 0;
if (!buff)
return -EFAULT;
if (*offp > 0)
return 0;
if (down_interruptible(&spike_dev.fop_sem))
return -ERESTARTSYS;
printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples);
up(&spike_dev.fop_sem);
return status;
}
static ssize_t spike_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos)
{
size_t len;
ssize_t status = 0;
if (down_interruptible(&spike_dev.fop_sem))
return -ERESTARTSYS;
memset(spike_dev.user_buff, 0, 16);
len = count > 8 ? 8 : count;
if (copy_from_user(spike_dev.user_buff, buff, len))
{
status = -EFAULT;
goto spike_write_done;
}
/* we'll act as if we looked at all the data */
status = count;
/* but we only care about the first 5 characters */
if (!strnicmp(spike_dev.user_buff, "inc", 3))
{
disable_irq(spike_dev.irq);
write_register(1,0x62);
resetbuffers();
printk(KERN_ALERT "4000 samples per second\n");
enable_irq(spike_dev.irq);
}
if (!strnicmp(spike_dev.user_buff, "dec", 3))
{
disable_irq(spike_dev.irq);
write_register(1,0x52);
resetbuffers();
printk(KERN_ALERT "1000 samples per second\n");
enable_irq(spike_dev.irq);
}
if (!strnicmp(spike_dev.user_buff, "stop", 4))
{
disable_irq(spike_dev.irq);
resetbuffers();
printk(KERN_ALERT "Driver stopped\n");
}
spike_write_done:
up(&spike_dev.fop_sem);
return status;
}
static const struct file_operations spike_fops = {
.owner = THIS_MODULE,
.open = spike_open,
.read = spike_read,
.write = spike_write,
.unlocked_ioctl = adc_ioctl,
};
static int __init spike_init_cdev(void)
{
int error;
spike_dev.devt = MKDEV(0, 0);
error = alloc_chrdev_region(&spike_dev.devt, 0, 1, this_driver_name);
if (error < 0)
{
printk(KERN_ALERT "alloc_chrdev_region() failed: %d \n",
error);
return -1;
}
cdev_init(&spike_dev.cdev, &spike_fops);
spike_dev.cdev.owner = THIS_MODULE;
error = cdev_add(&spike_dev.cdev, spike_dev.devt, 1);
if (error)
{
printk(KERN_ALERT "cdev_add() failed: %d\n", error);
unregister_chrdev_region(spike_dev.devt, 1);
return -1;
}
return 0;
}
static int __init spike_init_class(void)
{
spike_dev.class = class_create(THIS_MODULE, this_driver_name);
if (!spike_dev.class)
{
printk(KERN_ALERT "class_create() failed\n");
return -1;
}
if (!device_create(spike_dev.class, NULL, spike_dev.devt, NULL, this_driver_name))
{
printk(KERN_ALERT "device_create(..., %s) failed\n",
this_driver_name);
class_destroy(spike_dev.class);
return -1;
}
return 0;
}
static int __init spike_init(void)
{
int result;
memset(&spike_dev, 0, sizeof(spike_dev));
memset(&spike_ctl, 0, sizeof(spike_ctl));
sema_init(&spike_dev.spi_sem, 1);
sema_init(&spike_dev.fop_sem, 1);
buff_even = kmalloc(BUFF_SIZE, GFP_KERNEL);
buff_odd = kmalloc(BUFF_SIZE, GFP_KERNEL);
temp_buff = kmalloc(BUFF_SIZE, GFP_KERNEL);
if ( buff_even == 0 )
printk(KERN_ALERT "Failed to allocate buffer even\n");
if ( buff_odd == 0 )
printk(KERN_ALERT "Failed to allocate buffer odd\n");
if ( temp_buff == 0 )
printk(KERN_ALERT "Failed to temp buffer\n");
if (spike_init_cdev() < 0)
goto fail_1;
if (spike_init_class() < 0)
goto fail_2;
if (spike_init_spi() < 0)
goto fail_3;
result = request_irq(spike_dev.irq, adc_handler, IRQF_TRIGGER_RISING, "adc", &spike_dev);
if (result < 0)
{
printk(KERN_ALERT "request_irq failed: %d\n", result);
return -1;
}
return 0;
fail_3:
device_destroy(spike_dev.class, spike_dev.devt);
class_destroy(spike_dev.class);
fail_2:
cdev_del(&spike_dev.cdev);
unregister_chrdev_region(spike_dev.devt, 1);
fail_1:
return -1;
}
module_init(spike_init);
static void __exit spike_exit(void)
{
disable_irq(spike_dev.irq);
free_irq(spike_dev.irq, &spike_dev);
gpio_free(IRQ_PIN);
spi_unregister_device(spike_dev.spi_device);
spi_unregister_driver(&spike_driver);
device_destroy(spike_dev.class, spike_dev.devt);
class_destroy(spike_dev.class);
cdev_del(&spike_dev.cdev);
unregister_chrdev_region(spike_dev.devt, 1);
if (spike_ctl.tx_buff)
kfree(spike_ctl.tx_buff);
if (spike_ctl.rx_buff)
kfree(spike_ctl.rx_buff);
if (spike_dev.user_buff)
kfree(spike_dev.user_buff);
if ( buff_even != 0 )
kfree(buff_even);
if ( buff_odd != 0 )
kfree(buff_odd);
if ( temp_buff != 0 )
kfree(temp_buff);
printk(KERN_ALERT "Interrupt triggered %d Missed packet %d\n", sample_counter, num_miss_samples);
}
module_exit(spike_exit);
The interrupt handler crashes on the line
status = spi_async(spike_dev.spi_device, &spike_ctl.msg);
If i comment out this line everything runs fine but of course no data is read from SPI.
Muhammad, maybe you solved this issue by the time.
However, what I see is that you're using mutexes in the SPI completion handler (spike_completion_handler), which is executed in a context that cannot sleep.
Therefore, I would advise to use spinlocks instead.
This is safe to do, because count_lock always protects code that does not sleep.
That may not be the cause of your problem (did not read the whole code), but it's still better to do it this way.

Are there simple examples of how to parse a simple JSON file using the C-based YAJL library?

I know there is an Objective-C wrapper around YAJL, but this is a really fat thing which blows up the whole JASON parser to a ridiculous huge amount of 21 files, many of them with tiny scroll bars.
So to keep my app binary small I'd like to stick with the C-version of that parser. But I'm having a hard time finding any useful documentation for this rather than the wrapper.
Maybe someone who used the C-base can point out such a tutorial or documentation?
The documentation with C examples can be found here: http://lloyd.github.com/yajl/
The github repository with examples can be found here : https://github.com/lloyd/yajl
Here is a C example that reformats JSON from stdin:
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int reformat_null(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_null(g);
}
static int reformat_boolean(void * ctx, int boolean)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_bool(g, boolean);
}
static int reformat_number(void * ctx, const char * s, size_t l)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_number(g, s, l);
}
static int reformat_string(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_map_key(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_start_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_open(g);
}
static int reformat_end_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_close(g);
}
static int reformat_start_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_open(g);
}
static int reformat_end_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_close(g);
}
static yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
static void
usage(const char * progname)
{
fprintf(stderr, "%s: reformat json from stdin\n"
"usage: json_reformat [options]\n"
" -m minimize json rather than beautify (default)\n"
" -u allow invalid UTF8 inside strings during parsing\n",
progname);
exit(1);
}
int
main(int argc, char ** argv)
{
yajl_handle hand;
static unsigned char fileData[65536];
/* generator config */
yajl_gen g;
yajl_status stat;
size_t rd;
int retval = 0;
int a = 1;
g = yajl_gen_alloc(NULL);
yajl_gen_config(g, yajl_gen_beautify, 1);
yajl_gen_config(g, yajl_gen_validate_utf8, 1);
/* ok. open file. let's read and parse */
hand = yajl_alloc(&callbacks, NULL, (void *) g);
/* and let's allow comments by default */
yajl_config(hand, yajl_allow_comments, 1);
/* check arguments.*/
while ((a < argc) && (argv[a][0] == '-') && (strlen(argv[a]) > 1)) {
unsigned int i;
for ( i=1; i < strlen(argv[a]); i++) {
switch (argv[a][i]) {
case 'm':
yajl_gen_config(g, yajl_gen_beautify, 0);
break;
case 'u':
yajl_config(hand, yajl_dont_validate_strings, 1);
break;
default:
fprintf(stderr, "unrecognized option: '%c'\n\n",
argv[a][i]);
usage(argv[0]);
}
}
++a;
}
if (a < argc) {
usage(argv[0]);
}
for (;;) {
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
if (rd == 0) {
if (!feof(stdin)) {
fprintf(stderr, "error on file read.\n");
retval = 1;
}
break;
}
fileData[rd] = 0;
stat = yajl_parse(hand, fileData, rd);
if (stat != yajl_status_ok) break;
{
const unsigned char * buf;
size_t len;
yajl_gen_get_buf(g, &buf, &len);
fwrite(buf, 1, len, stdout);
yajl_gen_clear(g);
}
}
stat = yajl_complete_parse(hand);
if (stat != yajl_status_ok) {
unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
fprintf(stderr, "%s", (const char *) str);
yajl_free_error(hand, str);
retval = 1;
}
yajl_gen_free(g);
yajl_free(hand);
return retval;
}