bluetooth_rfcomm_channel_mac.mm 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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.
  4. #include "device/bluetooth/bluetooth_rfcomm_channel_mac.h"
  5. #include <memory>
  6. #include "base/check_op.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "device/bluetooth/bluetooth_classic_device_mac.h"
  9. #include "device/bluetooth/bluetooth_socket_mac.h"
  10. // A simple delegate class for an open RFCOMM channel that forwards methods to
  11. // its wrapped |channel_|.
  12. @interface BluetoothRfcommChannelDelegate
  13. : NSObject <IOBluetoothRFCOMMChannelDelegate> {
  14. @private
  15. raw_ptr<device::BluetoothRfcommChannelMac> _channel; // weak
  16. }
  17. - (instancetype)initWithChannel:(device::BluetoothRfcommChannelMac*)channel;
  18. @end
  19. @implementation BluetoothRfcommChannelDelegate
  20. - (instancetype)initWithChannel:(device::BluetoothRfcommChannelMac*)channel {
  21. if ((self = [super init]))
  22. _channel = channel;
  23. return self;
  24. }
  25. - (void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel
  26. status:(IOReturn)error {
  27. _channel->OnChannelOpenComplete(rfcommChannel, error);
  28. }
  29. - (void)rfcommChannelWriteComplete:(IOBluetoothRFCOMMChannel*)rfcommChannel
  30. refcon:(void*)refcon
  31. status:(IOReturn)error {
  32. _channel->OnChannelWriteComplete(rfcommChannel, refcon, error);
  33. }
  34. - (void)rfcommChannelData:(IOBluetoothRFCOMMChannel*)rfcommChannel
  35. data:(void*)dataPointer
  36. length:(size_t)dataLength {
  37. _channel->OnChannelDataReceived(rfcommChannel, dataPointer, dataLength);
  38. }
  39. - (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel*)rfcommChannel {
  40. _channel->OnChannelClosed(rfcommChannel);
  41. }
  42. @end
  43. namespace device {
  44. BluetoothRfcommChannelMac::BluetoothRfcommChannelMac(
  45. BluetoothSocketMac* socket,
  46. IOBluetoothRFCOMMChannel* channel)
  47. : channel_(channel),
  48. delegate_(nil) {
  49. SetSocket(socket);
  50. }
  51. BluetoothRfcommChannelMac::~BluetoothRfcommChannelMac() {
  52. [channel_ setDelegate:nil];
  53. [channel_ closeChannel];
  54. }
  55. // static
  56. std::unique_ptr<BluetoothRfcommChannelMac> BluetoothRfcommChannelMac::OpenAsync(
  57. BluetoothSocketMac* socket,
  58. IOBluetoothDevice* device,
  59. BluetoothRFCOMMChannelID channel_id,
  60. IOReturn* status) {
  61. DCHECK(socket);
  62. std::unique_ptr<BluetoothRfcommChannelMac> channel(
  63. new BluetoothRfcommChannelMac(socket, nil));
  64. // Retain the delegate, because IOBluetoothDevice's
  65. // |-openRFCOMMChannelAsync:withChannelID:delegate:| assumes that it can take
  66. // ownership of the delegate without calling |-retain| on it...
  67. DCHECK(channel->delegate_);
  68. [channel->delegate_ retain];
  69. IOBluetoothRFCOMMChannel* rfcomm_channel;
  70. *status = [device openRFCOMMChannelAsync:&rfcomm_channel
  71. withChannelID:channel_id
  72. delegate:channel->delegate_];
  73. if (*status == kIOReturnSuccess) {
  74. // Note: No need to retain the |rfcomm_channel| -- the returned channel is
  75. // already retained.
  76. channel->channel_.reset(rfcomm_channel);
  77. } else {
  78. channel.reset();
  79. }
  80. return channel;
  81. }
  82. void BluetoothRfcommChannelMac::SetSocket(BluetoothSocketMac* socket) {
  83. BluetoothChannelMac::SetSocket(socket);
  84. if (!this->socket())
  85. return;
  86. // Now that the socket is set, it's safe to associate a delegate, which can
  87. // call back to the socket.
  88. DCHECK(!delegate_);
  89. delegate_.reset(
  90. [[BluetoothRfcommChannelDelegate alloc] initWithChannel:this]);
  91. [channel_ setDelegate:delegate_];
  92. }
  93. IOBluetoothDevice* BluetoothRfcommChannelMac::GetDevice() {
  94. return [channel_ getDevice];
  95. }
  96. uint16_t BluetoothRfcommChannelMac::GetOutgoingMTU() {
  97. return [channel_ getMTU];
  98. }
  99. IOReturn BluetoothRfcommChannelMac::WriteAsync(void* data,
  100. uint16_t length,
  101. void* refcon) {
  102. DCHECK_LE(length, GetOutgoingMTU());
  103. return [channel_ writeAsync:data length:length refcon:refcon];
  104. }
  105. void BluetoothRfcommChannelMac::OnChannelOpenComplete(
  106. IOBluetoothRFCOMMChannel* channel,
  107. IOReturn status) {
  108. if (channel_) {
  109. DCHECK_EQ(channel_, channel);
  110. } else {
  111. // The (potentially) asynchronous connection occurred synchronously.
  112. // Should only be reachable from OpenAsync().
  113. DCHECK_EQ(status, kIOReturnSuccess);
  114. }
  115. socket()->OnChannelOpenComplete(
  116. BluetoothClassicDeviceMac::GetDeviceAddress([channel getDevice]), status);
  117. }
  118. void BluetoothRfcommChannelMac::OnChannelClosed(
  119. IOBluetoothRFCOMMChannel* channel) {
  120. DCHECK_EQ(channel_, channel);
  121. socket()->OnChannelClosed();
  122. }
  123. void BluetoothRfcommChannelMac::OnChannelDataReceived(
  124. IOBluetoothRFCOMMChannel* channel,
  125. void* data,
  126. size_t length) {
  127. DCHECK_EQ(channel_, channel);
  128. socket()->OnChannelDataReceived(data, length);
  129. }
  130. void BluetoothRfcommChannelMac::OnChannelWriteComplete(
  131. IOBluetoothRFCOMMChannel* channel,
  132. void* refcon,
  133. IOReturn status) {
  134. // Note: We use "CHECK" below to ensure we never run into unforeseen
  135. // occurrences of asynchronous callbacks, which could lead to data
  136. // corruption.
  137. CHECK_EQ(channel_, channel);
  138. socket()->OnChannelWriteComplete(refcon, status);
  139. }
  140. } // namespace device