2012-05-29 13:59:01 +03:00
/*
Copyright ( c ) 2010 , 2011 Code Aurora Forum . All rights reserved .
Copyright ( c ) 2011 , 2012 Intel Corp .
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 <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
# include <net/bluetooth/l2cap.h>
2012-05-29 13:59:02 +03:00
# include <net/bluetooth/a2mp.h>
2012-05-29 13:59:01 +03:00
static struct l2cap_ops a2mp_chan_ops = {
. name = " L2CAP A2MP channel " ,
} ;
static struct l2cap_chan * a2mp_chan_open ( struct l2cap_conn * conn )
{
struct l2cap_chan * chan ;
int err ;
chan = l2cap_chan_create ( ) ;
if ( ! chan )
return NULL ;
BT_DBG ( " chan %p " , chan ) ;
hci_conn_hold ( conn - > hcon ) ;
chan - > omtu = L2CAP_A2MP_DEFAULT_MTU ;
chan - > imtu = L2CAP_A2MP_DEFAULT_MTU ;
chan - > flush_to = L2CAP_DEFAULT_FLUSH_TO ;
chan - > ops = & a2mp_chan_ops ;
l2cap_chan_set_defaults ( chan ) ;
chan - > remote_max_tx = chan - > max_tx ;
chan - > remote_tx_win = chan - > tx_win ;
chan - > retrans_timeout = L2CAP_DEFAULT_RETRANS_TO ;
chan - > monitor_timeout = L2CAP_DEFAULT_MONITOR_TO ;
skb_queue_head_init ( & chan - > tx_q ) ;
chan - > mode = L2CAP_MODE_ERTM ;
err = l2cap_ertm_init ( chan ) ;
if ( err < 0 ) {
l2cap_chan_del ( chan , 0 ) ;
return NULL ;
}
chan - > conf_state = 0 ;
l2cap_chan_add ( conn , chan ) ;
chan - > remote_mps = chan - > omtu ;
chan - > mps = chan - > omtu ;
chan - > state = BT_CONNECTED ;
return chan ;
}
2012-05-29 13:59:02 +03:00
/* AMP Manager functions */
void amp_mgr_get ( struct amp_mgr * mgr )
{
BT_DBG ( " mgr %p " , mgr ) ;
kref_get ( & mgr - > kref ) ;
}
static void amp_mgr_destroy ( struct kref * kref )
{
struct amp_mgr * mgr = container_of ( kref , struct amp_mgr , kref ) ;
BT_DBG ( " mgr %p " , mgr ) ;
kfree ( mgr ) ;
}
int amp_mgr_put ( struct amp_mgr * mgr )
{
BT_DBG ( " mgr %p " , mgr ) ;
return kref_put ( & mgr - > kref , & amp_mgr_destroy ) ;
}
static struct amp_mgr * amp_mgr_create ( struct l2cap_conn * conn )
{
struct amp_mgr * mgr ;
struct l2cap_chan * chan ;
mgr = kzalloc ( sizeof ( * mgr ) , GFP_KERNEL ) ;
if ( ! mgr )
return NULL ;
BT_DBG ( " conn %p mgr %p " , conn , mgr ) ;
mgr - > l2cap_conn = conn ;
chan = a2mp_chan_open ( conn ) ;
if ( ! chan ) {
kfree ( mgr ) ;
return NULL ;
}
mgr - > a2mp_chan = chan ;
chan - > data = mgr ;
conn - > hcon - > amp_mgr = mgr ;
kref_init ( & mgr - > kref ) ;
return mgr ;
}