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, ®val, 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.
Related
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
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;
}
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;
}
I have list of background processes and their pid running in background in iphone got from following code. My projects requirement is-
(its like an antivirus)
Get information on each process
a. Name
b. Size
c. Last Modified Date/Time
d. Associated Files
e. What the process is accessing from all interfaces (storage, USB, Bluetooth, Wi-Fi etc)
f. Any other information available
Thanks in advance.
#import <mach/mach_host.h>
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "sys/sysctl.h"
#include <CoreFoundation/CoreFoundation.h>
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
- (void)viewDidLoad
{
[super viewDidLoad];
[self printProcessInfo];
}
-(int) printProcessInfo
{
int mib[5];
struct kinfo_proc *procs = NULL, *newprocs;
int i, st, nprocs;
size_t miblen, size;
/* Set up sysctl MIB */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ALL;
mib[3] = 0;
miblen = 4;
/* Get initial sizing */
st = sysctl(mib, miblen, NULL, &size, NULL, 0);
/* Repeat until we get them all ... */
do {
/* Room to grow */
size += size / 10;
newprocs = realloc(procs, size);
if (!newprocs) {
if (procs) {
free(procs);
}
perror("Error: realloc failed.");
return (0);
}
procs = newprocs;
st = sysctl(mib, miblen, procs, &size, NULL, 0);
} while (st == -1 && errno == ENOMEM);
if (st != 0) {
perror("Error: sysctl(KERN_PROC) failed.");
return (0);
}
/* Do we match the kernel? */
assert(size % sizeof(struct kinfo_proc) == 0);
nprocs = size / sizeof(struct kinfo_proc);
if (!nprocs) {
perror("Error: printProcessInfo.");
return(0);
}
printf(" PID\tName\n");
printf("-----\t--------------\n");
self.lists = [[NSMutableString alloc] init];
for (i = nprocs-1; i >=0; i--) {
printf("%5d\t%s\n",(int)procs[i].kp_proc.p_pid, procs[i].kp_proc.p_comm);
}
NSLog(#"%#",lists);
listsText.text = lists;
free(procs);
return (0);
}
answer a)name of process you are getting in above code.
answer d)to get associated files,pass pid of process to this function (we have got pid in questions code)-
void print_argv_of_pid(int pid) {
printf("%d\n", pid);
int mib[3], argmax, nargs, c = 0;
size_t size;
char *procargs, *sp, *np, *cp;
extern int eflg;
int show_args = 1;
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) {
goto ERROR_A;
}
/* Allocate space for the arguments. */
procargs = (char *)malloc(argmax);
if (procargs == NULL) {
goto ERROR_A;
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = pid;
size = (size_t)argmax;
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) {
goto ERROR_B;
}
memcpy(&nargs, procargs, sizeof(nargs));
cp = procargs + sizeof(nargs);
/* Skip the saved exec_path. */
for (; cp < &procargs[size]; cp++) {
if (*cp == '\0') {
/* End of exec_path reached. */
break;
}
}
if (cp == &procargs[size]) {
goto ERROR_B;
}
/* Skip trailing '\0' characters. */
for (; cp < &procargs[size]; cp++) {
if (*cp != '\0') {
/* Beginning of first argument reached. */
break;
}
}
if (cp == &procargs[size]) {
goto ERROR_B;
}
/* Save where the argv[0] string starts. */
sp = cp;
for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
if (*cp == '\0') {
c++;
if (np != NULL) {
/* Convert previous '\0'. */
*np = ' ';
} else {
/* *argv0len = cp - sp; */
}
/* Note location of current '\0'. */
np = cp;
if (!show_args) {
/*
* Don't convert '\0' characters to ' '.
* However, we needed to know that the
* command name was terminated, which we
* now know.
*/
break;
}
}
}
if (np == NULL || np == sp) {
/* Empty or unterminated string. */
goto ERROR_B;
}
/* Make a copy of the string. */
printf("%s\n", sp);
/* Clean up. */
free(procargs);
return;
ERROR_B:
free(procargs);
ERROR_A:
printf("error");
}
answer b),c)-size and access times-
struct stat st;
//pass filepath upto /.app/ to stat function (use 'componentsseparatedby' of nsstring apply on full path which we got in answer d's code above)
if (stat(filename, &st)) {
perror(filename);
} else {
printf("%s: mtime = %lld.%.9ld\n", filename, (long long)st.st_mtimespec.tv_sec, st.st_mtimespec.tv_nsec);
printf("File size: %lld bytes\n",
(long long) st.st_size);
printf("Last status change: %s", ctime(&st.st_ctime));
printf("Last file access: %s", ctime(&st.st_atime));
printf("Last file modification: %s", ctime(&st.st_mtime));
}
other information-
TO KILL THE PROCESS-
just pass pid of process to be killed-
int pid_exists(long pid)
{
int kill_ret;
// save some time if it's an invalid PID
if (pid < 0) {
return 0;
}
// if kill returns success of permission denied we know it's a valid PID
kill_ret = kill(pid , 0);
if ( (0 == kill_ret) || (EPERM == errno) ) {
return 1;
}
// otherwise return 0 for PID not found
return 0;
}
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;
}