154 lines
No EOL
3.8 KiB
C
154 lines
No EOL
3.8 KiB
C
/*
|
|
* muic_ccic.c
|
|
*
|
|
* Copyright (C) 2014 Samsung Electronics
|
|
* Thomas Ryu <smilesr.ryu@samsung.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
#include <linux/gpio.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/module.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/host_notify.h>
|
|
#include <linux/string.h>
|
|
#if defined (CONFIG_OF)
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_gpio.h>
|
|
#endif
|
|
|
|
#include <linux/muic/muic.h>
|
|
#if defined(CONFIG_MUIC_NOTIFIER)
|
|
#include <linux/muic/muic_notifier.h>
|
|
#endif
|
|
|
|
#if defined(CONFIG_USB_EXTERNAL_NOTIFY)
|
|
#include <linux/usb_notify.h>
|
|
#endif
|
|
|
|
#include "muic-internal.h"
|
|
#include "muic_coagent.h"
|
|
|
|
#if defined(CONFIG_USB_EXTERNAL_NOTIFY)
|
|
extern void muic_send_dock_intent(int type);
|
|
|
|
/*
|
|
* status: normal if 1, abnormal if 0
|
|
* return 0 on success, -1 on fail
|
|
*/
|
|
static int muic_noti_gamepad_status(int status, const char *sender)
|
|
{
|
|
uint val;
|
|
|
|
if (!sender) {
|
|
pr_info("%s:%s: Illegal argument!\n", MUIC_DEV_NAME, __func__);
|
|
return -1;
|
|
}
|
|
|
|
pr_info("%s:%s gamepas_status=[%s] from %s\n", MUIC_DEV_NAME, __func__,
|
|
status ? "normal" : "abnormal", sender);
|
|
|
|
val = status ? COA_STATUS_OK: COA_STATUS_NOK;
|
|
val <<= COAGENT_PARAM_BITS;
|
|
val |= COA_GAMEPAD_STATUS;
|
|
coagent_in(&val);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int muic_handle_usb_notification(struct notifier_block *nb,
|
|
unsigned long action, void *data)
|
|
{
|
|
muic_data_t *pmuic =
|
|
container_of(nb, muic_data_t, usb_nb);
|
|
|
|
switch (action) {
|
|
/* Abnormal device */
|
|
case EXTERNAL_NOTIFY_3S_NODEVICE:
|
|
pr_info("%s: 3S_NODEVICE(USB HOST Connection timeout)\n", __func__);
|
|
if (pmuic->attached_dev == ATTACHED_DEV_HMT_MUIC)
|
|
muic_set_hmt_status(1);
|
|
else if ((pmuic->attached_dev == ATTACHED_DEV_GAMEPAD_MUIC) ||
|
|
(pmuic->attached_dev == ATTACHED_DEV_OTG_MUIC))
|
|
pr_info("%s: Abnormal Gamepad -> do nothing.\n", __func__);
|
|
|
|
break;
|
|
|
|
/* Gamepad device connected */
|
|
case EXTERNAL_NOTIFY_DEVICE_CONNECT:
|
|
pr_info("%s: DEVICE_CONNECT(Gamepad)\n", __func__);
|
|
|
|
|
|
if ((pmuic->attached_dev != ATTACHED_DEV_GAMEPAD_MUIC) &&
|
|
(pmuic->attached_dev != ATTACHED_DEV_OTG_MUIC)) {
|
|
pr_info("%s: Unexpected scenario.n", __func__);
|
|
break;
|
|
}
|
|
|
|
pmuic->is_gamepad = true;
|
|
if (pmuic->attached_dev == ATTACHED_DEV_OTG_MUIC)
|
|
muic_send_dock_intent(MUIC_DOCK_GAMEPAD_WITH_EARJACK);
|
|
|
|
muic_noti_gamepad_status(1, "USB");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return NOTIFY_DONE;
|
|
}
|
|
|
|
|
|
void muic_register_usb_notifier(muic_data_t *pmuic)
|
|
{
|
|
int ret = 0;
|
|
|
|
pr_info("%s: Registering EXTERNAL_NOTIFY_DEV_MUIC.\n", __func__);
|
|
|
|
|
|
ret = usb_external_notify_register(&pmuic->usb_nb,
|
|
muic_handle_usb_notification, EXTERNAL_NOTIFY_DEV_MUIC);
|
|
if (ret < 0) {
|
|
pr_info("%s: USB Noti. is not ready.\n", __func__);
|
|
return;
|
|
}
|
|
|
|
pr_info("%s: done.\n", __func__);
|
|
}
|
|
|
|
void muic_unregister_usb_notifier(muic_data_t *pmuic)
|
|
{
|
|
int ret = 0;
|
|
|
|
pr_info("%s\n", __func__);
|
|
|
|
ret = usb_external_notify_unregister(&pmuic->usb_nb);
|
|
if (ret < 0) {
|
|
pr_info("%s: USB Noti. unregister error.\n", __func__);
|
|
return;
|
|
}
|
|
|
|
pr_info("%s: done.\n", __func__);
|
|
}
|
|
#else
|
|
void muic_register_usb_notifier(muic_data_t *pmuic){}
|
|
void muic_unregister_usb_notifier(muic_data_t *pmuic){}
|
|
#endif |