rc: Add support for GPIO based IR Receiver driver.
Subsystems (3)
PATCH v2 1/1 rc: Add support for GPIO based IR Receiver driver.
Adds GPIO based IR Receiver driver. It decodes signals using decoders available in rc framework.
--- drivers/media/rc/Kconfig | 9 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/gpio-ir-recv.c | 189 +++++++++++++++++++++++++++++++++++++++ include/media/gpio-ir-recv.h | 23 +++++ 4 files changed, 222 insertions(+), 0 deletions(-) create mode 100644 drivers/media/rc/gpio-ir-recv.c create mode 100644 include/media/gpio-ir-recv.h
drivers/media/rc/Kconfig +9 -0
@@ -256,4 +256,13 @@ config RC_LOOPBACK To compile this driver as a module, choose M here: the module will be called rc_loopback. +config IR_GPIO_CIR + tristate "GPIO IR remote control" + depends on RC_CORE + ---help--- + Say Y if you want to use GPIO based IR Receiver. + + To compile this driver as a module, choose M here: the module will + be called gpio-ir-recv. + endif #RC_CORE
drivers/media/rc/Makefile +1 -0
@@ -25,3 +25,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o +obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
drivers/media/rc/gpio-ir-recv.c new file +189 -0
189 lines not on this page · raw message
include/media/gpio-ir-recv.h new file +23 -0
@@ -0,0 +1,23 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __GPIO_IR_RECV_H__ +#define __GPIO_IR_RECV_H__ + +struct gpio_ir_recv_platform_data { +unsigned int gpio_nr; +bool active_low; +bool can_wakeup; +}; + +#endif /* __GPIO_IR_RECV_H__ */ +
Signature · 2 lines
Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Quoted 65 lines · Ravi Kumar V
Adds GPIO based IR Receiver driver. It decodes signals using decoders available in rc framework.
Signed-off-by Ravi Kumar V <[email protected]>--- drivers/media/rc/Kconfig | 9 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/gpio-ir-recv.c | 189 +++++++++++++++++++++++++++++++++++++++ include/media/gpio-ir-recv.h | 23 +++++ 4 files changed, 222 insertions(+), 0 deletions(-) create mode 100644 drivers/media/rc/gpio-ir-recv.c create mode 100644 include/media/gpio-ir-recv.hdrivers/media/rc/Kconfig +9
-0@@ -256,4 +256,13 @@ config RC_LOOPBACK To compile this driver as a module, choose M here: the module will be called rc_loopback. +config IR_GPIO_CIR + tristate "GPIO IR remote control" + depends on RC_CORE + ---help--- + Say Y if you want to use GPIO based IR Receiver. + + To compile this driver as a module, choose M here: the module will + be called gpio-ir-recv. + endif #RC_COREdrivers/media/rc/Makefile +1
-0@@ -25,3 +25,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o +obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.odrivers/media/rc/gpio-ir-recv.c new file +19
-0@@ -0,0 +1,189 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/platform_device.h>
drivers/media/rc/gpio-ir-recv.c line 29
Quoted 10 lines
drivers/media/rc/gpio-ir-recv.c new file +10
-0+#include <linux/irq.h> +#include <media/rc-core.h> +#include <media/gpio-ir-recv.h> + +#define GPIO_IR_DRIVER_NAME "gpio-rc-recv" +#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" + +struct gpio_rc_dev { +struct rc_dev *rcdev; +struct mutex lock;
I could be completely wrong here, but is this lock necessary since data is only read, and it's only used by a single interrupt handler?
Quoted 17 lines
drivers/media/rc/gpio-ir-recv.c new file +17
-0+unsigned int gpio_nr; +bool active_low; +bool can_wakeup; +}; + +static irqreturn_t gpio_ir_recv_irq (int irq,void *dev_id) +{ +struct gpio_rc_dev *gpio_dev = dev_id; +unsigned int gval; +int rc =0 ; +enum raw_event_type type =IR_SPACE ; + +mutex_lock (&gpio_dev->lock); + gval =gpio_get_value_cansleep (gpio_dev->gpio_nr); + +if (gval <0 ) + goto err_get_value;
drivers/media/rc/gpio-ir-recv.c line 56
Quoted 10 lines
drivers/media/rc/gpio-ir-recv.c new file +10
-0+ +if (gpio_dev->active_low) + gval = !gval; + +if (gval ==1 ) + type =IR_PULSE ; + + rc =ir_raw_event_store_edge (gpio_dev->rcdev, type); +if (rc <0 ) + goto err_get_value;
Since ir_raw_event_store_edge just puts the event into a kfifo for the ir-raw thread to handle, does this really have to be a threaded IRQ? I'd have thought you'd get more accurate time measurements (especially on slower/embedded CPUs) if the IRQ is serviced as soon as possible.
If it needs to be threaded so that the gpio read can sleep, perhaps it could make use of a hard irq if the gpio can be accessed atomically, and fall back to threaded if not.
Quoted 27 lines
drivers/media/rc/gpio-ir-recv.c new file +27
-0+ +ir_raw_event_handle (gpio_dev->rcdev); + +err_get_value: +mutex_unlock (&gpio_dev->lock); + +return IRQ_HANDLED ; +} + +static int __devinit gpio_ir_recv_probe (struct platform_device *pdev) +{ +struct gpio_rc_dev *gpio_dev; +struct rc_dev *rcdev; +const struct gpio_ir_recv_platform_data *pdata = + pdev->dev.platform_data; +int rc; + +if (!pdata) +return -EINVAL ; + +if (pdata->gpio_nr <0 ) +return -EINVAL ; + + gpio_dev =kzalloc (sizeof (struct gpio_rc_dev ),GFP_KERNEL ); +if (!gpio_dev) +return -ENOMEM ; +
drivers/media/rc/gpio-ir-recv.c line 93
Quoted 10 lines
drivers/media/rc/gpio-ir-recv.c new file +10
-0+mutex_init (&gpio_dev->lock); + + rcdev =rc_allocate_device (); +if (!rcdev) { + rc = -ENOMEM ; + goto err_allocate_device; + } + + rcdev->driver_type =RC_DRIVER_IR_RAW ; + rcdev->allowed_protos =RC_TYPE_NEC ;
Is this necessary, since the driver is protocol agnostic?
Quoted 27 lines
drivers/media/rc/gpio-ir-recv.c new file +27
-0+ rcdev->input_name =GPIO_IR_DEVICE_NAME ; + rcdev->input_id.bustype =BUS_HOST ; + rcdev->driver_name =GPIO_IR_DRIVER_NAME ; + rcdev->map_name =RC_MAP_EMPTY ; + + gpio_dev->rcdev = rcdev; + gpio_dev->gpio_nr = pdata->gpio_nr; + gpio_dev->active_low = pdata->active_low; + gpio_dev->can_wakeup = pdata->can_wakeup; + + + rc =gpio_request (pdata->gpio_nr,"gpio-ir-recv" ); +if (rc <0 ) + goto err_gpio_request; + rc =gpio_direction_input (pdata->gpio_nr); +if (rc <0 ) + goto err_gpio_direction_input; + + rc =rc_register_device (rcdev); +if (rc <0 ) { +dev_err (&pdev->dev,"failed to register rc device\n" ); + goto err_register_rc_device; + } + +platform_set_drvdata (pdev, gpio_dev); + + rc = request_threaded_irq(gpio_to_irq(pdata->gpio_nr),
drivers/media/rc/gpio-ir-recv.c line 130
Quoted 10 lines
drivers/media/rc/gpio-ir-recv.c new file +10
-0+NULL , gpio_ir_recv_irq, +IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING , + "gpio-ir-recv-irq", gpio_dev); +if (rc <0 ) + goto err_request_irq; + +if (pdata->can_wakeup == true) { + rc =enable_irq_wake (gpio_to_irq (pdata->gpio_nr)); +if (rc <0 ) + goto err_enable_irq_wake;
would this be better done in a suspend/resume callback, along with device_may_wakeup and device_set_wakeup_capable/device_init_wakeup so that it can be enabled and disabled with sysfs?
Cheers
James
Quoted 97 lines
drivers/media/rc/gpio-ir-recv.c new file +59
-0+ } + +return 0 ; + +err_enable_irq_wake: +free_irq (gpio_to_irq (gpio_dev->gpio_nr), gpio_dev); +err_request_irq: +platform_set_drvdata (pdev,NULL ); +rc_unregister_device (rcdev); +err_register_rc_device: +err_gpio_direction_input: +gpio_free (pdata->gpio_nr); +err_gpio_request: +rc_free_device (rcdev); + rcdev =NULL ; +err_allocate_device: +mutex_destroy (&gpio_dev->lock); +kfree (gpio_dev); +return rc; +} + +static int __devexit gpio_ir_recv_remove(struct platform_device *pdev) +{ +struct gpio_rc_dev *gpio_dev =platform_get_drvdata (pdev); + +disable_irq_wake (gpio_to_irq (gpio_dev->gpio_nr)); +free_irq (gpio_to_irq (gpio_dev->gpio_nr), gpio_dev); +platform_set_drvdata (pdev,NULL ); +rc_unregister_device (gpio_dev->rcdev); +gpio_free (gpio_dev->gpio_nr); +rc_free_device (gpio_dev->rcdev); +mutex_destroy (&gpio_dev->lock); +kfree (gpio_dev); +return 0 ; +} + +static struct platform_driver gpio_ir_recv_driver = { + .probe = gpio_ir_recv_probe, + .remove =__devexit_p (gpio_ir_recv_remove), + .driver = { + .name =GPIO_IR_DRIVER_NAME , + .owner =THIS_MODULE , + }, +}; + +static int __init gpio_ir_recv_init (void ) +{ +return platform_driver_register (&gpio_ir_recv_driver); +} +module_init (gpio_ir_recv_init); + +static void __exit gpio_ir_recv_exit(void) +{ +platform_driver_unregister (&gpio_ir_recv_driver); +} +module_exit (gpio_ir_recv_exit); + +MODULE_DESCRIPTION ("GPIO IR Receiver driver" ); +MODULE_LICENSE ("GPL v2" );include/media/gpio-ir-recv.h new file +23
-0@@ -0,0 +1,23 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __GPIO_IR_RECV_H__ +#define __GPIO_IR_RECV_H__ + +struct gpio_ir_recv_platform_data { +unsigned int gpio_nr; +bool active_low; +bool can_wakeup; +}; + +#endif /* __GPIO_IR_RECV_H__ */ +Signature · 8 lines
Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Quoted 71 lines · James Hogan
Quoted 70 lines · Ravi Kumar V
Adds GPIO based IR Receiver driver. It decodes signals using decoders available in rc framework.
Signed-off-by Ravi Kumar V<[email protected]>--- drivers/media/rc/Kconfig | 9 ++ drivers/media/rc/Makefile | 1 + drivers/media/rc/gpio-ir-recv.c | 189 +++++++++++++++++++++++++++++++++++++++ include/media/gpio-ir-recv.h | 23 +++++ 4 files changed, 222 insertions(+), 0 deletions(-)create mode 100644
drivers/media/rc/gpio-ir-recv.ccreate mode 100644include/media/gpio-ir-recv.hdrivers/media/rc/Kconfig +9
-0@@ -256,4 +256,13 @@ config RC_LOOPBACK To compile this driver as a module, choose M here: the module will be called rc_loopback. +config IR_GPIO_CIR + tristate "GPIO IR remote control" + depends on RC_CORE + ---help--- + Say Y if you want to use GPIO based IR Receiver. + + To compile this driver as a module, choose M here: the module will + be called gpio-ir-recv. + endif #RC_COREdrivers/media/rc/Makefile +1
-0@@ -25,3 +25,4 @@ obj-$(CONFIG_IR_REDRAT3) += redrat3.o obj-$(CONFIG_IR_STREAMZAP) += streamzap.o obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o +obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.odrivers/media/rc/gpio-ir-recv.c new file +24
-0@@ -0,0 +1,189 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/gpio.h> +#include <linux/slab.h> +#include <linux/platform_device.h> +#include <linux/irq.h> +#include <media/rc-core.h> +#include <media/gpio-ir-recv.h> + +#define GPIO_IR_DRIVER_NAME "gpio-rc-recv"
Quoted 9 lines
drivers/media/rc/gpio-ir-recv.c line 29
Quoted 5 lines
drivers/media/rc/gpio-ir-recv.c new file +5
-0+#define GPIO_IR_DEVICE_NAME "gpio_ir_recv" + +struct gpio_rc_dev { +struct rc_dev *rcdev; +struct mutex lock;I could be completely wrong here, but is this lock necessary since data is only read, and it's only used by a single interrupt handler?
Yes i have checked you are right, i will take it out
Quoted 33 lines
Quoted 17 lines
drivers/media/rc/gpio-ir-recv.c new file +17
-0+unsigned int gpio_nr; +bool active_low; +bool can_wakeup; +}; + +static irqreturn_t gpio_ir_recv_irq (int irq,void *dev_id) +{ +struct gpio_rc_dev *gpio_dev = dev_id; +unsigned int gval; +int rc =0 ; +enum raw_event_type type =IR_SPACE ; + +mutex_lock (&gpio_dev->lock); + gval =gpio_get_value_cansleep (gpio_dev->gpio_nr); + +if (gval<0 ) + goto err_get_value;drivers/media/rc/gpio-ir-recv.c line 56
Quoted 10 lines
drivers/media/rc/gpio-ir-recv.c new file +10
-0+ +if (gpio_dev->active_low) + gval = !gval; + +if (gval ==1 ) + type =IR_PULSE ; + + rc =ir_raw_event_store_edge (gpio_dev->rcdev, type); +if (rc<0 ) + goto err_get_value;Since
ir_raw_event_store_edgejust puts the event into a kfifo for the ir-raw thread to handle, does this really have to be a threaded IRQ? I'd have thought you'd get more accurate time measurements (especially on slower/embedded CPUs) if the IRQ is serviced as soon as possible.
Quoted 4 lines
If it needs to be threaded so that the gpio read can sleep, perhaps it could make use of a hard irq if the gpio can be accessed atomically, and fall back to threaded if not.
yes you are right i will see, I will distinguish between gpio atomic & sleep by using gpio_cansleep in probe and switch to appropriate hard/threaded irq.
Quoted 31 lines
Quoted 31 lines
drivers/media/rc/gpio-ir-recv.c new file +31
-0+ +ir_raw_event_handle (gpio_dev->rcdev); + +err_get_value: +mutex_unlock (&gpio_dev->lock); + +return IRQ_HANDLED ; +} + +static int __devinit gpio_ir_recv_probe (struct platform_device *pdev) +{ +struct gpio_rc_dev *gpio_dev; +struct rc_dev *rcdev; +const struct gpio_ir_recv_platform_data *pdata = + pdev->dev.platform_data; +int rc; + +if (!pdata) +return -EINVAL ; + +if (pdata->gpio_nr<0 ) +return -EINVAL ; + + gpio_dev =kzalloc (sizeof (struct gpio_rc_dev ),GFP_KERNEL ); +if (!gpio_dev) +return -ENOMEM ; + +mutex_init (&gpio_dev->lock); + + rcdev =rc_allocate_device (); +if (!rcdev) {
Quoted 8 lines
drivers/media/rc/gpio-ir-recv.c line 93
Quoted 6 lines
drivers/media/rc/gpio-ir-recv.c new file +6
-0+ rc = -ENOMEM ; + goto err_allocate_device; + } + + rcdev->driver_type =RC_DRIVER_IR_RAW ; + rcdev->allowed_protos =RC_TYPE_NEC ;Is this necessary, since the driver is protocol agnostic?
I will change it to RC_TYPE_ALL
Quoted 34 lines
Quoted 34 lines
drivers/media/rc/gpio-ir-recv.c new file +33
-0+ rcdev->input_name =GPIO_IR_DEVICE_NAME ; + rcdev->input_id.bustype =BUS_HOST ; + rcdev->driver_name =GPIO_IR_DRIVER_NAME ; + rcdev->map_name =RC_MAP_EMPTY ; + + gpio_dev->rcdev = rcdev; + gpio_dev->gpio_nr = pdata->gpio_nr; + gpio_dev->active_low = pdata->active_low; + gpio_dev->can_wakeup = pdata->can_wakeup; + + + rc =gpio_request (pdata->gpio_nr,"gpio-ir-recv" ); +if (rc<0 ) + goto err_gpio_request; + rc =gpio_direction_input (pdata->gpio_nr); +if (rc<0 ) + goto err_gpio_direction_input; + + rc =rc_register_device (rcdev); +if (rc<0 ) { +dev_err (&pdev->dev,"failed to register rc device\n" ); + goto err_register_rc_device; + } + +platform_set_drvdata (pdev, gpio_dev); + + rc =request_threaded_irq (gpio_to_irq (pdata->gpio_nr), +NULL , gpio_ir_recv_irq, +IRQF_TRIGGER_FALLING |IRQF_TRIGGER_RISING , +"gpio-ir-recv-irq" , gpio_dev); +if (rc<0 ) + goto err_request_irq; +
Quoted 9 lines
drivers/media/rc/gpio-ir-recv.c line 130
Quoted 4 lines
drivers/media/rc/gpio-ir-recv.c new file +4
-0+if (pdata->can_wakeup == true) { + rc =enable_irq_wake (gpio_to_irq (pdata->gpio_nr)); +if (rc<0 ) + goto err_enable_irq_wake;would this be better done in a suspend/resume callback, along with
device_may_wakeupand device_set_wakeup_capable/device_init_wakeup so that it can be enabled and disabled with sysfs?
Yes i will look into this
Quoted 95 lines
Cheers
JamesQuoted 92 lines
drivers/media/rc/gpio-ir-recv.c new file +59
-0+ } + +return 0 ; + +err_enable_irq_wake: +free_irq (gpio_to_irq (gpio_dev->gpio_nr), gpio_dev); +err_request_irq: +platform_set_drvdata (pdev,NULL ); +rc_unregister_device (rcdev); +err_register_rc_device: +err_gpio_direction_input: +gpio_free (pdata->gpio_nr); +err_gpio_request: +rc_free_device (rcdev); + rcdev =NULL ; +err_allocate_device: +mutex_destroy (&gpio_dev->lock); +kfree (gpio_dev); +return rc; +} + +static int __devexit gpio_ir_recv_remove(struct platform_device *pdev) +{ +struct gpio_rc_dev *gpio_dev =platform_get_drvdata (pdev); + +disable_irq_wake (gpio_to_irq (gpio_dev->gpio_nr)); +free_irq (gpio_to_irq (gpio_dev->gpio_nr), gpio_dev); +platform_set_drvdata (pdev,NULL ); +rc_unregister_device (gpio_dev->rcdev); +gpio_free (gpio_dev->gpio_nr); +rc_free_device (gpio_dev->rcdev); +mutex_destroy (&gpio_dev->lock); +kfree (gpio_dev); +return 0 ; +} + +static struct platform_driver gpio_ir_recv_driver = { + .probe = gpio_ir_recv_probe, + .remove =__devexit_p (gpio_ir_recv_remove), + .driver = { + .name =GPIO_IR_DRIVER_NAME , + .owner =THIS_MODULE , + }, +}; + +static int __init gpio_ir_recv_init (void ) +{ +return platform_driver_register (&gpio_ir_recv_driver); +} +module_init (gpio_ir_recv_init); + +static void __exit gpio_ir_recv_exit(void) +{ +platform_driver_unregister (&gpio_ir_recv_driver); +} +module_exit (gpio_ir_recv_exit); + +MODULE_DESCRIPTION ("GPIO IR Receiver driver" ); +MODULE_LICENSE ("GPL v2" );include/media/gpio-ir-recv.h new file +23
-1@@ -0,0 +1,23 @@ +/* Copyright (c) 2012, Code Aurora Forum. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 and +* only version 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#ifndef __GPIO_IR_RECV_H__ +#define __GPIO_IR_RECV_H__ + +struct gpio_ir_recv_platform_data { +unsigned int gpio_nr; +bool active_low; +bool can_wakeup; +}; + +#endif /* __GPIO_IR_RECV_H__ */ + --Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
Quoted 5 lines
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Thanks,
Ravi Kumar V
Signature · 2 lines
Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.