void send_debug(unsigned char type, const char *format, ...) { // make a run over the vararg parameter to determine the size va_list args; va_start(args, format); unsigned int size = vsnprintf(NULL, 0, format, args) + 1; va_end(args); // properly align the char array to sizeof(int) // under the assumption, that sizeof(int) % sizeof(char) = 0 #define cpi (sizeof(int) / sizeof(char)) size += (cpi - (size % cpi)) % cpi; // FIXME check, that the resulting size is smaller than the maxsize of the protocol!? // if(size > ) // allocate memory and store the formatted string char *c = malloc(sizeof(char) * size); va_start(args, format); vsnprintf(c, size, format, args); va_end(args); // encode and send a message (using sizeof(int) as size) struct Message *m = encode_debug(type, size / cpi); message_payload(m, (int*)c, size / cpi); medium_send(m); // free allocated memory message_free(m); free(c); }
/* * init and exit */ static int __init imapx200_encode_init(void) { if (platform_driver_register(&imapx200_encode_driver)) { encode_error("Fail to register platform driver for IMAPX200 Encoder Driver\n"); return -EPERM; } encode_debug("IMAPX200 Hantro 7280 Encode Driver init OK\n"); return ENCODE_RET_OK; }
/* release */ static int imapx200_encode_release(struct inode *inode, struct file *file) { mutex_lock(&encode_lock); encode_open_count--; if (encode_open_count == 0) { encode_disable_hw_power(); } mutex_unlock(&encode_lock); encode_debug("IMAPX200 Encode release OK\n"); return ENCODE_RET_OK; }
/* open */ static int imapx200_encode_open(struct inode *inode, struct file *file) { mutex_lock(&encode_lock); if (encode_open_count == 0) { encode_enable_hw_power(); } encode_open_count++; mutex_unlock(&encode_lock); file->private_data = (void *)(&encode_param); encode_debug("IMAPX200 Encode open OK\n"); return ENCODE_RET_OK; }
/* ioctl */ static int imapx200_encode_ioctl(struct inode *inode, struct file *file, \ unsigned int cmd, unsigned long arg) { int ret = -1; /* cmd check */ if (_IOC_TYPE(cmd) != HX280ENC_IOC_MAGIC) { return -ENOTTY; } if (_IOC_NR(cmd) > HX280ENC_IOC_MAXNR) { return -ENOTTY; } /* check command by command feature READ/WRITE */ if (_IOC_DIR(cmd) & _IOC_READ) { ret = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd)); } else if (_IOC_DIR(cmd) & _IOC_WRITE) { ret = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd)); } if (ret) { return -EFAULT; } switch (cmd) { case HX280ENC_IOCGHWOFFSET: __put_user(encode_param.reg_base_phys_addr, (unsigned int *)arg); break; case HX280ENC_IOCGHWIOSIZE: __put_user(IMAPX200_ENCODE_ACT_REG_SIZE, (unsigned int *)arg); break; case HX280ENC_IOC_CLI: case HX280ENC_IOC_STI: case HX280ENC_IOCHARDRESET: encode_debug("current ioctl command unsupported yet\n"); break; default: encode_error("encode driver unknow ioctl command\n"); break; } return ENCODE_RET_OK; }
/* irq handle function */ static irqreturn_t imapx200_encode_irq_handle(int irq, void *dev_id) { encode_param_t *dev = (encode_param_t *)dev_id; unsigned int irq_status = 0; /* get interrupt register status */ irq_status = readl(dev->reg_base_virt_addr + 0x04); if (irq_status & 0x01) { writel(irq_status & (~0x01), dev->reg_base_virt_addr + 0x04); encode_poll_mark = 1; wake_up(&wait_encode); return IRQ_HANDLED; } else { encode_debug("An unknown interrupt detected\n"); return IRQ_HANDLED; } }
/* remove */ static int imapx200_encode_remove(struct platform_device *pdev) { /* disable hardware */ writel(0, encode_param.reg_base_virt_addr + 0x38); /* clean encode irq */ writel(0, encode_param.reg_base_virt_addr + 0x04); /* unmap registers address */ iounmap((void *)(encode_param.reg_base_virt_addr)); /* release resource */ release_mem_region(encode_param.reg_base_phys_addr, \ encode_param.reg_reserved_size); /* release source */ if (encode_param.resource_mem != NULL) { release_resource(encode_param.resource_mem); kfree(encode_param.resource_mem); encode_param.resource_mem = NULL; } /* release irq */ free_irq(IRQ_VENC, pdev); /* unregister encode driver */ encode_driver_unregister(); /* disable encode clock */ clk_disable(imap_venc_clock); mutex_destroy(&encode_lock); encode_debug("IMAPX200 encode driver remove OK\n"); return ENCODE_RET_OK; }
static void __exit imapx200_encode_exit(void) { platform_driver_unregister(&imapx200_encode_driver); encode_debug("IMAPX200 Encode Driver exit OK\n"); }
/* probe */ static int imapx200_encode_probe(struct platform_device *pdev) { int ret = -1; unsigned int size = 0; struct resource *res = NULL; encode_debug("In imapx200_encode_probe\n"); /* get encode hardware clock and enable it */ imap_venc_clock = clk_get(&pdev->dev, "venc"); if (imap_venc_clock == NULL) { encode_error("Fail to get encode hardware source\n"); return -ENOENT; } clk_enable(imap_venc_clock); /* close 7280 ic if uboot has done something needs ic powered on */ encode_disable_hw_power(); /* initialize encode open count */ encode_open_count = 0; /* initialize global varaibles */ memset(&encode_param, 0x00, sizeof(encode_param_t)); /* initialize wait queue for poll system call */ init_waitqueue_head(&wait_encode); /* get register base resource */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { encode_error("Fail to get encode platform device resource\n"); return -ENOENT; } /* request memory region */ size = res->end - res->start + 1; encode_param.reg_reserved_size = size; encode_param.resource_mem = request_mem_region(res->start, size, pdev->name); if (encode_param.resource_mem == NULL) { encode_error("Fail to get IMAPX200 encode register memory region\n"); return -ENOENT; } encode_param.reg_base_phys_addr = res->start; /* remap register physics address nocache */ encode_param.reg_base_virt_addr = ioremap_nocache(res->start, size); if (encode_param.reg_base_virt_addr == NULL) { encode_error("Fail to ioremap IMAPX200 encode register base address\n"); return -EINVAL; } /* get and config irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { encode_error("Fail to get IMAPX200 encode irq resource\n"); return -ENOENT; } if (res->start != IRQ_VENC) { encode_error("Get wrong irq number for IMAPX200 encode\n"); return -ENOENT; } /* request for irq */ ret = request_irq(res->start, imapx200_encode_irq_handle, IRQF_DISABLED, \ pdev->name, (void *)(&encode_param)); if (ret) { encode_error("Fail to request irq for IMAPX200 encode device\n"); return ret; } /* register driver device */ if (encode_driver_register() != ENCODE_RET_OK) { return ENCODE_RET_ERROR; } /* reset hardware registers */ reset_hw_reg_encode(); mutex_init(&encode_lock); encode_debug("IMAPX200 encode driver probe OK, major: %d minor: %d\n", \ encode_param.major, encode_param.minor); return ENCODE_RET_OK; }