Automated Commit: Committing new LKGM version 6953.0.0 for chromeos.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_l2cap_channel_mac.mm
blob2f38f3f89df11763b34a0ae7ad048eda90fe8c97
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/bluetooth/bluetooth_l2cap_channel_mac.h"
7 #include "base/logging.h"
8 #include "base/mac/sdk_forward_declarations.h"
9 #include "device/bluetooth/bluetooth_device_mac.h"
10 #include "device/bluetooth/bluetooth_socket_mac.h"
12 // A simple delegate class for an open L2CAP channel that forwards methods to
13 // its wrapped |channel_|.
14 @interface BluetoothL2capChannelDelegate
15     : NSObject <IOBluetoothL2CAPChannelDelegate> {
16  @private
17   device::BluetoothL2capChannelMac* channel_;  // weak
20 - (id)initWithChannel:(device::BluetoothL2capChannelMac*)channel;
22 @end
24 @implementation BluetoothL2capChannelDelegate
26 - (id)initWithChannel:(device::BluetoothL2capChannelMac*)channel {
27   if ((self = [super init]))
28     channel_ = channel;
30   return self;
33 - (void)l2capChannelOpenComplete:(IOBluetoothL2CAPChannel*)l2capChannel
34                           status:(IOReturn)error {
35   channel_->OnChannelOpenComplete(l2capChannel, error);
38 - (void)l2capChannelWriteComplete:(IOBluetoothL2CAPChannel*)l2capChannel
39                            refcon:(void*)refcon
40                            status:(IOReturn)error {
41   channel_->OnChannelWriteComplete(l2capChannel, refcon, error);
44 - (void)l2capChannelData:(IOBluetoothL2CAPChannel*)l2capChannel
45                     data:(void*)dataPointer
46                   length:(size_t)dataLength {
47   channel_->OnChannelDataReceived(l2capChannel, dataPointer, dataLength);
50 - (void)l2capChannelClosed:(IOBluetoothL2CAPChannel*)l2capChannel {
51   channel_->OnChannelClosed(l2capChannel);
54 // These methods are marked as optional in the 10.8 SDK, but not in the 10.6
55 // SDK. These empty implementations can be removed once we drop the 10.6 SDK.
56 - (void)l2capChannelReconfigured:(IOBluetoothL2CAPChannel*)l2capChannel {
58 - (void)l2capChannelQueueSpaceAvailable:(IOBluetoothL2CAPChannel*)l2capChannel {
61 @end
63 namespace device {
65 BluetoothL2capChannelMac::BluetoothL2capChannelMac(
66     BluetoothSocketMac* socket,
67     IOBluetoothL2CAPChannel* channel)
68     : channel_(channel),
69       delegate_(nil) {
70   SetSocket(socket);
73 BluetoothL2capChannelMac::~BluetoothL2capChannelMac() {
74   [channel_ setDelegate:nil];
75   [channel_ closeChannel];
78 // static
79 scoped_ptr<BluetoothL2capChannelMac> BluetoothL2capChannelMac::OpenAsync(
80     BluetoothSocketMac* socket,
81     IOBluetoothDevice* device,
82     BluetoothL2CAPPSM psm,
83     IOReturn* status) {
84   DCHECK(socket);
85   scoped_ptr<BluetoothL2capChannelMac> channel(
86       new BluetoothL2capChannelMac(socket, nil));
88   // Retain the delegate, because IOBluetoothDevice's
89   // |-openL2CAPChannelAsync:withPSM:delegate:| assumes that it can take
90   // ownership of the delegate without calling |-retain| on it...
91   DCHECK(channel->delegate_);
92   [channel->delegate_ retain];
93   IOBluetoothL2CAPChannel* l2cap_channel;
94   *status = [device openL2CAPChannelAsync:&l2cap_channel
95                                   withPSM:psm
96                                  delegate:channel->delegate_];
97   if (*status == kIOReturnSuccess)
98     channel->channel_.reset([l2cap_channel retain]);
99   else
100     channel.reset();
102   return channel.Pass();
105 void BluetoothL2capChannelMac::SetSocket(BluetoothSocketMac* socket) {
106   BluetoothChannelMac::SetSocket(socket);
107   if (!this->socket())
108     return;
110   // Now that the socket is set, it's safe to associate a delegate, which can
111   // call back to the socket.
112   DCHECK(!delegate_);
113   delegate_.reset(
114       [[BluetoothL2capChannelDelegate alloc] initWithChannel:this]);
115   [channel_ setDelegate:delegate_];
118 IOBluetoothDevice* BluetoothL2capChannelMac::GetDevice() {
119   return [channel_ getDevice];
122 uint16_t BluetoothL2capChannelMac::GetOutgoingMTU() {
123   return [channel_ outgoingMTU];
126 IOReturn BluetoothL2capChannelMac::WriteAsync(void* data,
127                                               uint16_t length,
128                                               void* refcon) {
129   DCHECK_LE(length, GetOutgoingMTU());
130   return [channel_ writeAsync:data length:length refcon:refcon];
133 void BluetoothL2capChannelMac::OnChannelOpenComplete(
134     IOBluetoothL2CAPChannel* channel,
135     IOReturn status) {
136   if (channel_) {
137     DCHECK_EQ(channel_, channel);
138   } else {
139     // The (potentially) asynchronous connection occurred synchronously.
140     // Should only be reachable from OpenAsync().
141     DCHECK_EQ(status, kIOReturnSuccess);
142   }
144   socket()->OnChannelOpenComplete(
145       BluetoothDeviceMac::GetDeviceAddress([channel getDevice]), status);
148 void BluetoothL2capChannelMac::OnChannelClosed(
149     IOBluetoothL2CAPChannel* channel) {
150   DCHECK_EQ(channel_, channel);
151   socket()->OnChannelClosed();
154 void BluetoothL2capChannelMac::OnChannelDataReceived(
155     IOBluetoothL2CAPChannel* channel,
156     void* data,
157     size_t length) {
158   DCHECK_EQ(channel_, channel);
159   socket()->OnChannelDataReceived(data, length);
162 void BluetoothL2capChannelMac::OnChannelWriteComplete(
163     IOBluetoothL2CAPChannel* channel,
164     void* refcon,
165     IOReturn status) {
166   // Note: We use "CHECK" below to ensure we never run into unforeseen
167   // occurrences of asynchronous callbacks, which could lead to data
168   // corruption.
169   CHECK_EQ(channel_, channel);
170   socket()->OnChannelWriteComplete(refcon, status);
173 }  // namespace device