Mark //testing/perf target testonly.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_rfcomm_channel_mac.mm
blob693a29658570a65e110c580ad72b3a416341a6fb
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_rfcomm_channel_mac.h"
7 #include "base/logging.h"
8 #include "device/bluetooth/bluetooth_device_mac.h"
9 #include "device/bluetooth/bluetooth_socket_mac.h"
11 // A simple delegate class for an open RFCOMM channel that forwards methods to
12 // its wrapped |channel_|.
13 @interface BluetoothRfcommChannelDelegate
14     : NSObject <IOBluetoothRFCOMMChannelDelegate> {
15  @private
16   device::BluetoothRfcommChannelMac* channel_;  // weak
19 - (id)initWithChannel:(device::BluetoothRfcommChannelMac*)channel;
21 @end
23 @implementation BluetoothRfcommChannelDelegate
25 - (id)initWithChannel:(device::BluetoothRfcommChannelMac*)channel {
26   if ((self = [super init]))
27     channel_ = channel;
29   return self;
32 - (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel
33                            status:(IOReturn)error {
34   channel_->OnChannelOpenComplete(rfcommChannel, error);
37 - (void)rfcommChannelWriteComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel
38                             refcon:(void*)refcon
39                             status:(IOReturn)error {
40   channel_->OnChannelWriteComplete(rfcommChannel, refcon, error);
43 - (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel
44                      data:(void*)dataPointer
45                    length:(size_t)dataLength {
46   channel_->OnChannelDataReceived(rfcommChannel, dataPointer, dataLength);
49 - (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel {
50   channel_->OnChannelClosed(rfcommChannel);
53 @end
55 namespace device {
57 BluetoothRfcommChannelMac::BluetoothRfcommChannelMac(
58     BluetoothSocketMac* socket,
59     IOBluetoothRFCOMMChannel* channel)
60     : channel_(channel),
61       delegate_(nil) {
62   SetSocket(socket);
65 BluetoothRfcommChannelMac::~BluetoothRfcommChannelMac() {
66   [channel_ setDelegate:nil];
67   [channel_ closeChannel];
70 // static
71 scoped_ptr<BluetoothRfcommChannelMac> BluetoothRfcommChannelMac::OpenAsync(
72     BluetoothSocketMac* socket,
73     IOBluetoothDevice* device,
74     BluetoothRFCOMMChannelID channel_id,
75     IOReturn* status) {
76   DCHECK(socket);
77   scoped_ptr<BluetoothRfcommChannelMac> channel(
78       new BluetoothRfcommChannelMac(socket, nil));
80   // Retain the delegate, because IOBluetoothDevice's
81   // |-openRFCOMMChannelAsync:withChannelID:delegate:| assumes that it can take
82   // ownership of the delegate without calling |-retain| on it...
83   DCHECK(channel->delegate_);
84   [channel->delegate_ retain];
85   IOBluetoothRFCOMMChannel* rfcomm_channel;
86   *status = [device openRFCOMMChannelAsync:&rfcomm_channel
87                              withChannelID:channel_id
88                                   delegate:channel->delegate_];
89   if (*status == kIOReturnSuccess) {
90     // Note: No need to retain the |rfcomm_channel| -- the returned channel is
91     // already retained.
92     channel->channel_.reset(rfcomm_channel);
93   } else {
94     channel.reset();
95   }
97   return channel.Pass();
100 void BluetoothRfcommChannelMac::SetSocket(BluetoothSocketMac* socket) {
101   BluetoothChannelMac::SetSocket(socket);
102   if (!this->socket())
103     return;
105   // Now that the socket is set, it's safe to associate a delegate, which can
106   // call back to the socket.
107   DCHECK(!delegate_);
108   delegate_.reset(
109       [[BluetoothRfcommChannelDelegate alloc] initWithChannel:this]);
110   [channel_ setDelegate:delegate_];
113 IOBluetoothDevice* BluetoothRfcommChannelMac::GetDevice() {
114   return [channel_ getDevice];
117 uint16_t BluetoothRfcommChannelMac::GetOutgoingMTU() {
118   return [channel_ getMTU];
121 IOReturn BluetoothRfcommChannelMac::WriteAsync(void* data,
122                                                uint16_t length,
123                                                void* refcon) {
124   DCHECK_LE(length, GetOutgoingMTU());
125   return [channel_ writeAsync:data length:length refcon:refcon];
128 void BluetoothRfcommChannelMac::OnChannelOpenComplete(
129     IOBluetoothRFCOMMChannel* channel,
130     IOReturn status) {
131   if (channel_) {
132     DCHECK_EQ(channel_, channel);
133   } else {
134     // The (potentially) asynchronous connection occurred synchronously.
135     // Should only be reachable from OpenAsync().
136     DCHECK_EQ(status, kIOReturnSuccess);
137   }
139   socket()->OnChannelOpenComplete(
140       BluetoothDeviceMac::GetDeviceAddress([channel getDevice]), status);
143 void BluetoothRfcommChannelMac::OnChannelClosed(
144     IOBluetoothRFCOMMChannel* channel) {
145   DCHECK_EQ(channel_, channel);
146   socket()->OnChannelClosed();
149 void BluetoothRfcommChannelMac::OnChannelDataReceived(
150     IOBluetoothRFCOMMChannel* channel,
151     void* data,
152     size_t length) {
153   DCHECK_EQ(channel_, channel);
154   socket()->OnChannelDataReceived(data, length);
157 void BluetoothRfcommChannelMac::OnChannelWriteComplete(
158     IOBluetoothRFCOMMChannel* channel,
159     void* refcon,
160     IOReturn status) {
161   // Note: We use "CHECK" below to ensure we never run into unforeseen
162   // occurrences of asynchronous callbacks, which could lead to data
163   // corruption.
164   CHECK_EQ(channel_, channel);
165   socket()->OnChannelWriteComplete(refcon, status);
168 }  // namespace device