OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/gamepad/xbox_data_fetcher_mac.h" | 5 #include "content/browser/gamepad/xbox_data_fetcher_mac.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
11 #include <CoreFoundation/CoreFoundation.h> | 11 #include <CoreFoundation/CoreFoundation.h> |
12 #include <IOKit/IOCFPlugIn.h> | 12 #include <IOKit/IOCFPlugIn.h> |
13 #include <IOKit/IOKitLib.h> | 13 #include <IOKit/IOKitLib.h> |
14 #include <IOKit/usb/IOUSBLib.h> | 14 #include <IOKit/usb/IOUSBLib.h> |
15 #include <IOKit/usb/USB.h> | 15 #include <IOKit/usb/USB.h> |
16 | 16 |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/mac/foundation_util.h" | 18 #include "base/mac/foundation_util.h" |
19 | 19 |
| 20 using blink::WebGamepad; |
| 21 |
| 22 namespace content { |
| 23 |
20 namespace { | 24 namespace { |
21 const int kVendorMicrosoft = 0x045e; | 25 const int kVendorMicrosoft = 0x045e; |
22 const int kProductXbox360Controller = 0x028e; | 26 const int kProductXbox360Controller = 0x028e; |
23 const int kProductXboxOneController = 0x02d1; | 27 const int kProductXboxOneController = 0x02d1; |
24 | 28 |
25 const int kXbox360ReadEndpoint = 1; | 29 const int kXbox360ReadEndpoint = 1; |
26 const int kXbox360ControlEndpoint = 2; | 30 const int kXbox360ControlEndpoint = 2; |
27 | 31 |
28 const int kXboxOneReadEndpoint = 2; | 32 const int kXboxOneReadEndpoint = 2; |
29 const int kXboxOneControlEndpoint = 1; | 33 const int kXboxOneControlEndpoint = 1; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 kLeftThumbDeadzone, | 230 kLeftThumbDeadzone, |
227 &normalized_data->axes[0], | 231 &normalized_data->axes[0], |
228 &normalized_data->axes[1]); | 232 &normalized_data->axes[1]); |
229 NormalizeAxis(data.stick_right_x, | 233 NormalizeAxis(data.stick_right_x, |
230 data.stick_right_y, | 234 data.stick_right_y, |
231 kRightThumbDeadzone, | 235 kRightThumbDeadzone, |
232 &normalized_data->axes[2], | 236 &normalized_data->axes[2], |
233 &normalized_data->axes[3]); | 237 &normalized_data->axes[3]); |
234 } | 238 } |
235 | 239 |
| 240 void CopyNSStringAsUTF16LittleEndian( |
| 241 NSString* src, blink::WebUChar* dest, size_t dest_len) { |
| 242 NSData* as16 = [src dataUsingEncoding:NSUTF16LittleEndianStringEncoding]; |
| 243 memset(dest, 0, dest_len); |
| 244 [as16 getBytes:dest length:dest_len - sizeof(blink::WebUChar)]; |
| 245 } |
| 246 |
236 } // namespace | 247 } // namespace |
237 | 248 |
238 XboxController::XboxController(Delegate* delegate) | 249 XboxController::XboxController(Delegate* delegate) |
239 : device_(NULL), | 250 : device_(NULL), |
240 interface_(NULL), | 251 interface_(NULL), |
241 device_is_open_(false), | 252 device_is_open_(false), |
242 interface_is_open_(false), | 253 interface_is_open_(false), |
243 read_buffer_size_(0), | 254 read_buffer_size_(0), |
244 led_pattern_(LED_NUM_PATTERNS), | 255 led_pattern_(LED_NUM_PATTERNS), |
245 location_id_(0), | 256 location_id_(0), |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
616 buffer); | 627 buffer); |
617 if (kr != KERN_SUCCESS) { | 628 if (kr != KERN_SUCCESS) { |
618 delete[] buffer; | 629 delete[] buffer; |
619 IOError(); | 630 IOError(); |
620 return; | 631 return; |
621 } | 632 } |
622 } | 633 } |
623 | 634 |
624 //----------------------------------------------------------------------------- | 635 //----------------------------------------------------------------------------- |
625 | 636 |
626 XboxDataFetcher::XboxDataFetcher(Delegate* delegate) | 637 XboxDataFetcher::XboxDataFetcher() |
627 : delegate_(delegate), | 638 : listening_(false), |
628 listening_(false), | |
629 source_(NULL), | 639 source_(NULL), |
630 port_(NULL) { | 640 port_(NULL) { |
631 } | 641 } |
632 | 642 |
633 XboxDataFetcher::~XboxDataFetcher() { | 643 XboxDataFetcher::~XboxDataFetcher() { |
634 while (!controllers_.empty()) { | 644 while (!controllers_.empty()) { |
635 RemoveController(*controllers_.begin()); | 645 RemoveController(*controllers_.begin()); |
636 } | 646 } |
637 UnregisterFromNotifications(); | 647 UnregisterFromNotifications(); |
638 } | 648 } |
639 | 649 |
| 650 void XboxDataFetcher::GetGamepadData(bool devices_changed_hint) { |
| 651 // This just loops through all the connected pads and "pings" them to indicate |
| 652 // that they're still active. |
| 653 for (const auto& controller : controllers_) { |
| 654 provider()->GetPadState(GAMEPAD_SOURCE_MAC_XBOX, controller->location_id()); |
| 655 } |
| 656 } |
| 657 |
| 658 void XboxDataFetcher::OnAddedToProvider() { |
| 659 RegisterForNotifications(); |
| 660 } |
| 661 |
640 void XboxDataFetcher::DeviceAdded(void* context, io_iterator_t iterator) { | 662 void XboxDataFetcher::DeviceAdded(void* context, io_iterator_t iterator) { |
641 DCHECK(context); | 663 DCHECK(context); |
642 XboxDataFetcher* fetcher = static_cast<XboxDataFetcher*>(context); | 664 XboxDataFetcher* fetcher = static_cast<XboxDataFetcher*>(context); |
643 io_service_t ref; | 665 io_service_t ref; |
644 while ((ref = IOIteratorNext(iterator))) { | 666 while ((ref = IOIteratorNext(iterator))) { |
645 base::mac::ScopedIOObject<io_service_t> scoped_ref(ref); | 667 base::mac::ScopedIOObject<io_service_t> scoped_ref(ref); |
646 XboxController* controller = new XboxController(fetcher); | 668 XboxController* controller = new XboxController(fetcher); |
647 if (controller->OpenDevice(ref)) { | 669 if (controller->OpenDevice(ref)) { |
648 fetcher->AddController(controller); | 670 fetcher->AddController(controller); |
649 } else { | 671 } else { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 if ((*i)->location_id() == location_id) | 790 if ((*i)->location_id() == location_id) |
769 return *i; | 791 return *i; |
770 } | 792 } |
771 return NULL; | 793 return NULL; |
772 } | 794 } |
773 | 795 |
774 void XboxDataFetcher::AddController(XboxController* controller) { | 796 void XboxDataFetcher::AddController(XboxController* controller) { |
775 DCHECK(!ControllerForLocation(controller->location_id())) | 797 DCHECK(!ControllerForLocation(controller->location_id())) |
776 << "Controller with location ID " << controller->location_id() | 798 << "Controller with location ID " << controller->location_id() |
777 << " already exists in the set of controllers."; | 799 << " already exists in the set of controllers."; |
| 800 |
| 801 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_MAC_XBOX, |
| 802 controller->location_id()); |
| 803 if (!state) { |
| 804 delete controller; |
| 805 return; // No available slot for this device |
| 806 } |
| 807 |
778 controllers_.insert(controller); | 808 controllers_.insert(controller); |
779 delegate_->XboxDeviceAdd(controller); | 809 |
| 810 controller->SetLEDPattern( |
| 811 (XboxController::LEDPattern)(XboxController::LED_FLASH_TOP_LEFT + |
| 812 controller->location_id())); |
| 813 |
| 814 NSString* ident = [NSString stringWithFormat: |
| 815 @"%@ (STANDARD GAMEPAD Vendor: %04x Product: %04x)", |
| 816 controller->GetControllerType() == XboxController::XBOX_360_CONTROLLER |
| 817 ? @"Xbox 360 Controller" |
| 818 : @"Xbox One Controller", |
| 819 controller->GetProductId(), controller->GetVendorId()]; |
| 820 CopyNSStringAsUTF16LittleEndian( |
| 821 ident, |
| 822 state->data.id, |
| 823 sizeof(state->data.id)); |
| 824 |
| 825 CopyNSStringAsUTF16LittleEndian( |
| 826 @"standard", |
| 827 state->data.mapping, |
| 828 sizeof(state->data.mapping)); |
| 829 |
| 830 state->data.connected = true; |
| 831 state->data.axesLength = 4; |
| 832 state->data.buttonsLength = 17; |
| 833 state->data.timestamp = 0; |
| 834 state->mapper = 0; |
| 835 state->axis_mask = 0; |
| 836 state->button_mask = 0; |
780 } | 837 } |
781 | 838 |
782 void XboxDataFetcher::RemoveController(XboxController* controller) { | 839 void XboxDataFetcher::RemoveController(XboxController* controller) { |
783 delegate_->XboxDeviceRemove(controller); | |
784 controllers_.erase(controller); | 840 controllers_.erase(controller); |
785 delete controller; | 841 delete controller; |
786 } | 842 } |
787 | 843 |
788 void XboxDataFetcher::RemoveControllerByLocationID(uint32_t location_id) { | 844 void XboxDataFetcher::RemoveControllerByLocationID(uint32_t location_id) { |
789 XboxController* controller = NULL; | 845 XboxController* controller = NULL; |
790 for (std::set<XboxController*>::iterator i = controllers_.begin(); | 846 for (std::set<XboxController*>::iterator i = controllers_.begin(); |
791 i != controllers_.end(); | 847 i != controllers_.end(); |
792 ++i) { | 848 ++i) { |
793 if ((*i)->location_id() == location_id) { | 849 if ((*i)->location_id() == location_id) { |
794 controller = *i; | 850 controller = *i; |
795 break; | 851 break; |
796 } | 852 } |
797 } | 853 } |
798 if (controller) | 854 if (controller) |
799 RemoveController(controller); | 855 RemoveController(controller); |
800 } | 856 } |
801 | 857 |
802 void XboxDataFetcher::XboxControllerGotData(XboxController* controller, | 858 void XboxDataFetcher::XboxControllerGotData(XboxController* controller, |
803 const XboxController::Data& data) { | 859 const XboxController::Data& data) { |
804 delegate_->XboxValueChanged(controller, data); | 860 PadState* state = provider()->GetPadState(GAMEPAD_SOURCE_MAC_XBOX, |
| 861 controller->location_id()); |
| 862 if (!state) |
| 863 return; // No available slot for this device |
| 864 |
| 865 WebGamepad& pad = state->data; |
| 866 |
| 867 for (size_t i = 0; i < 6; i++) { |
| 868 pad.buttons[i].pressed = data.buttons[i]; |
| 869 pad.buttons[i].value = data.buttons[i] ? 1.0f : 0.0f; |
| 870 } |
| 871 pad.buttons[6].pressed = data.triggers[0] > kDefaultButtonPressedThreshold; |
| 872 pad.buttons[6].value = data.triggers[0]; |
| 873 pad.buttons[7].pressed = data.triggers[1] > kDefaultButtonPressedThreshold; |
| 874 pad.buttons[7].value = data.triggers[1]; |
| 875 for (size_t i = 8; i < 17; i++) { |
| 876 pad.buttons[i].pressed = data.buttons[i - 2]; |
| 877 pad.buttons[i].value = data.buttons[i - 2] ? 1.0f : 0.0f; |
| 878 } |
| 879 for (size_t i = 0; i < arraysize(data.axes); i++) { |
| 880 pad.axes[i] = data.axes[i]; |
| 881 } |
| 882 |
| 883 pad.timestamp = base::TimeTicks::Now().ToInternalValue(); |
805 } | 884 } |
806 | 885 |
807 void XboxDataFetcher::XboxControllerError(XboxController* controller) { | 886 void XboxDataFetcher::XboxControllerError(XboxController* controller) { |
808 RemoveController(controller); | 887 RemoveController(controller); |
809 } | 888 } |
| 889 |
| 890 } // namespace content |
OLD | NEW |