From f486127615f06a7503d1abc0da922cdb38d682e8 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Sun, 30 May 2021 13:47:36 -0400 Subject: [PATCH] Bluetooth pr rebased (#552 and #540) * btdrv: expand upon and refine event data definitions * btdrv changes for 12.0.0 * btdrv: Various fixes, added enums, etc. Co-authored-by: ndeadly <24677491+ndeadly@users.noreply.github.com> --- nx/include/switch/services/btdrv.h | 505 ++++++++++++++++------- nx/include/switch/services/btdrv_types.h | 162 ++++++-- nx/source/services/btdrv.c | 145 +++++-- 3 files changed, 593 insertions(+), 219 deletions(-) diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 694ecf4f..0126d8e1 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -1,7 +1,7 @@ /** * @file btdrv.h * @brief Bluetooth driver (btdrv) service IPC wrapper. - * @author yellows8 + * @author yellows8, ndeadly * @copyright libnx Authors */ #pragma once @@ -14,215 +14,276 @@ /// Data for \ref btdrvGetEventInfo. The data stored here depends on the \ref BtdrvEventType. typedef struct { union { - u8 data[0x400]; ///< Raw data. + u8 data[0x400]; ///< Raw data. struct { - u32 val; ///< Value - } type0; ///< ::BtdrvEventType_Unknown0 + u32 val; ///< Value + } type0; ///< ::BtdrvEventTypeOld_Unknown0 struct { - u8 name[0xF9]; ///< Device name, NUL-terminated string. - BtdrvAddress addr; ///< Device address. - u8 reserved_xFF[0x10]; ///< Reserved - u8 class_of_device[0x3]; ///< Class of Device. - u8 unk_x112[0x4]; ///< Set to fixed value u32 0x1. - u8 reserved_x116[0xFA]; ///< Reserved - u8 reserved_x210[0x5C]; ///< Reserved - u8 name2[0xF9]; ///< Device name, NUL-terminated string. Same as name above, except starting at index 1. - u8 rssi[0x4]; ///< s32 RSSI - u8 name3[0x4]; ///< Two bytes which are the same as name[11-12]. - u8 reserved_x36D[0x10]; ///< Reserved - } inquiry_device; ///< ::BtdrvEventType_InquiryDevice + union { + struct { + char name[0xF9]; ///< Device name, NUL-terminated string. + BtdrvAddress addr; ///< Device address. + u8 reserved_xFF[0x10]; ///< Reserved + BtdrvClassOfDevice class_of_device; ///< Class of Device. + u8 unk_x112[0x4]; ///< Set to fixed value u32 0x1. + u8 reserved_x116[0xFA]; ///< Reserved + u8 reserved_x210[0x5C]; ///< Reserved + char name2[0xF9]; ///< Device name, NUL-terminated string. Same as name above, except starting at index 1. + u8 rssi[0x4]; ///< s32 RSSI + u8 name3[0x4]; ///< Two bytes which are the same as name[11-12]. + u8 reserved_x36D[0x10]; ///< Reserved + } v1; ///< [1.0.0-11.0.1] + + struct { + BtdrvAddress addr; ///< Device address. + char name[0xF9]; ///< Device name, NUL-terminated string. + BtdrvClassOfDevice class_of_device; ///< Class of Device. + u8 reserved[0x6]; ///< Reserved + } v12; ///< [12.0.0+] + }; + } inquiry_device; ///< ::BtdrvEventType_InquiryDevice struct { - u32 status; ///< Status: 0 = stopped, 1 = started. - } inquiry_status; ///< ::BtdrvEventType_InquiryStatus + union { + struct { + BtdrvInquiryStatus status; ///< \ref BtdrvInquiryStatus + } v1; ///< [1.0.0-11.0.1] + + struct { + u8 status; ///< \ref BtdrvInquiryStatus + u8 pad[3]; ///< Padding + u32 service_mask; ///< Services value from \ref btdrvStartInquiry when starting, otherwise this is value 0. + } v12; ///< [12.0.0+] + }; + } inquiry_status; ///< ::BtdrvEventType_InquiryStatus struct { - BtdrvAddress addr; ///< Device address. - u8 name[0xF9]; ///< Device name, NUL-terminated string. - u8 class_of_device[0x3]; ///< Class of Device. - } pairing_pin_code_request; ///< ::BtdrvEventType_PairingPinCodeRequest + BtdrvAddress addr; ///< Device address. + char name[0xF9]; ///< Device name, NUL-terminated string. + BtdrvClassOfDevice class_of_device; ///< Class of Device. + } pairing_pin_code_request; ///< ::BtdrvEventType_PairingPinCodeRequest struct { - BtdrvAddress addr; ///< Device address. - u8 name[0xF9]; ///< Device name, NUL-terminated string. - u8 class_of_device[0x3]; ///< Class of Device. - u8 pad[2]; ///< Padding - u32 type; ///< 0 = SSP confirm request, 3 = SSP passkey notification. - s32 passkey; ///< Passkey, only set when the above field is value 3. - } ssp_request; ///< ::BtdrvEventType_SspRequest + union { + struct { + BtdrvAddress addr; ///< Device address. + char name[0xF9]; ///< Device name, NUL-terminated string. + BtdrvClassOfDevice class_of_device; ///< Class of Device. + u8 pad[2]; ///< Padding + u32 type; ///< 0 = SSP confirm request, 3 = SSP passkey notification. + s32 passkey; ///< Passkey, only set when the above field is value 3. + } v1; ///< [1.0.0-11.0.1] + + struct { + BtdrvAddress addr; ///< Device address. + char name[0xF9]; ///< Device name, NUL-terminated string. + BtdrvClassOfDevice class_of_device; ///< Class of Device. + u8 flag; ///< bool flag for Just Works. With SSP passkey notification this is always 0. + u8 pad; ///< Padding + s32 passkey; ///< Passkey + } v12; ///< [12.0.0+] + }; + } ssp_request; ///< ::BtdrvEventType_SspRequest struct { - u32 status; ///< Status, always 0 except with ::BtdrvConnectionEventType_Status: 2 = ACL Link is now Resumed, 9 = connection failed (pairing/authentication failed, or opening the hid connection failed). - BtdrvAddress addr; ///< Device address. - u8 pad[2]; ///< Padding - u32 type; ///< \ref BtdrvConnectionEventType - } connection; ///< ::BtdrvEventType_Connection + union { + struct { + u32 status; ///< Status, always 0 except with ::BtdrvConnectionEventType_Status: 2 = ACL Link is now Resumed, 9 = connection failed (pairing/authentication failed, or opening the hid connection failed). + BtdrvAddress addr; ///< Device address. + u8 pad[2]; ///< Padding + u32 type; ///< \ref BtdrvConnectionEventType + } v1; ///< [1.0.0-11.0.1] + + struct { + u32 type; ///< \ref BtdrvConnectionEventType + BtdrvAddress addr; ///< Device address. + u8 reserved[0xfe]; ///< Reserved + } v12; ///< [12.0.0+] + }; + } connection; ///< ::BtdrvEventType_Connection struct { - u16 reason; ///< \ref BtdrvFatalReason - } bluetooth_crash; ///< ::BtdrvEventType_BluetoothCrash + BtdrvAddress addr; ///< Device address. + u8 status; ///< Status flag: 1 = success, 0 = failure. + u8 value; ///< Tsi value, when the above indicates success. + } tsi; ///< ::BtdrvEventType_Tsi + + struct { + BtdrvAddress addr; ///< Device address. + u8 status; ///< Status flag: 1 = success, 0 = failure. + u8 value; ///< Input bool value from \ref btdrvEnableBurstMode, when the above indicates success. + } burst_mode; ///< ::BtdrvEventType_BurstMode + + struct { + BtdrvAddress addr; ///< Device address. + u8 status; ///< Status flag: 1 = success, 0 = failure. + u8 flag; ///< Bool flag, when the above indicates success. + } set_zero_retransmission; ///< ::BtdrvEventType_SetZeroRetransmission + + struct { + u8 status; ///< Status flag: 1 = success, 0 = failure. + u8 pad[0x3]; ///< Padding + u32 count; ///< Count value. + } pending_connections; ///< ::BtdrvEventType_PendingConnections + + struct { + BtdrvAddress addr; ///< Device address. + u8 status; ///< Status flag: 1 = success, 0 = failure. + } move_to_secondary_piconet; ///< ::BtdrvEventType_MoveToSecondaryPiconet + + struct { + u16 reason; ///< \ref BtdrvFatalReason + } bluetooth_crash; ///< ::BtdrvEventType_BluetoothCrash }; } BtdrvEventInfo; /// Data for \ref btdrvGetHidEventInfo. The data stored here depends on the \ref BtdrvHidEventType. typedef struct { union { - u8 data[0x480]; ///< Raw data. + u8 data[0x480]; ///< Raw data. struct { - BtdrvAddress addr; ///< Device address. - u8 pad[2]; ///< Padding - u32 status; ///< Status: 0 = hid connection opened, 2 = hid connection closed, 8 = failed to open hid connection. - } connection; ///< ::BtdrvHidEventType_Connection + BtdrvAddress addr; ///< Device address. + u8 pad[2]; ///< Padding + BtdrvHidConnectionStatus status; ///< \ref BtdrvHidConnectionStatus + } connection; ///< ::BtdrvHidEventType_Connection struct { - u32 type; ///< \ref BtdrvExtEventType, controls which data is stored below. + u32 type; ///< \ref BtdrvExtEventType, controls which data is stored below. union { struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - } set_tsi; ///< ::BtdrvExtEventType_SetTsi + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + } set_tsi; ///< ::BtdrvExtEventType_SetTsi struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - } exit_tsi; ///< ::BtdrvExtEventType_ExitTsi + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + } exit_tsi; ///< ::BtdrvExtEventType_ExitTsi struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - } set_burst_mode; ///< ::BtdrvExtEventType_SetBurstMode + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + } set_burst_mode; ///< ::BtdrvExtEventType_SetBurstMode struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - } exit_burst_mode; ///< ::BtdrvExtEventType_ExitBurstMode + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + } exit_burst_mode; ///< ::BtdrvExtEventType_ExitBurstMode struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - u8 pad[2]; ///< Padding - u8 flag; ///< Flag - } set_zero_retransmission; ///< ::BtdrvExtEventType_SetZeroRetransmission + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + u8 pad[2]; ///< Padding + u8 flag; ///< Flag + } set_zero_retransmission; ///< ::BtdrvExtEventType_SetZeroRetransmission struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Unused - u8 pad[2]; ///< Padding - u32 count; ///< Count value. - } pending_connections; ///< ::BtdrvExtEventType_PendingConnections + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Unused + u8 pad[2]; ///< Padding + u32 count; ///< Count value. + } pending_connections; ///< ::BtdrvExtEventType_PendingConnections struct { - u32 status; ///< 0 for success, non-zero for error. - BtdrvAddress addr; ///< Device address. - } move_to_secondary_piconet; ///< ::BtdrvExtEventType_MoveToSecondaryPiconet + u32 status; ///< 0 for success, non-zero for error. + BtdrvAddress addr; ///< Device address. + } move_to_secondary_piconet; ///< ::BtdrvExtEventType_MoveToSecondaryPiconet }; - } ext; ///< ::BtdrvHidEventType_Ext + } ext; ///< ::BtdrvHidEventType_Ext [1.0.0-11.0.1] }; } BtdrvHidEventInfo; /// Data for \ref btdrvGetHidReportEventInfo. The data stored here depends on the \ref BtdrvHidEventType. typedef struct { union { - u8 data[0x480]; ///< Raw data. - - struct { - u32 unk_x0; ///< Always 0. - u8 unk_x4; ///< Always 0. - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 pad; ///< Padding - u16 size; ///< Size of the below data. - u8 data[]; ///< Data. - } data_report; ///< ::BtdrvHidEventType_Data + u8 data[0x480]; ///< Raw data. struct { union { - u8 data[0xC]; ///< Raw data. + struct { + struct { + BtdrvAddress addr; + u8 pad[2]; + u32 res; + u32 size; + } hdr; + u8 unused[0x3]; ///< Unused + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 unused2[0x3]; ///< Unused + BtdrvHidData report; + } v1; ///< [1.0.0-6.2.0] struct { - u32 res; ///< 0 = success, non-zero = error. - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 pad[2]; ///< Padding + u8 unused[0x3]; ///< Unused + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 unused2[0x3]; ///< Unused + BtdrvHidData report; + } v7; ///< [7.0.0-8.1.1] + + struct { + u32 res; ///< Always 0. + u8 unk_x4; ///< Always 0. + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 pad; ///< Padding + BtdrvHidReport report; + } v9; ///< [9.0.0+] + }; + } data_report; ///< ::BtdrvHidEventType_DataReport + + struct { + union { + u8 rawdata[0xC]; ///< Raw data. + + struct { + u32 res; ///< 0 = success, non-zero = error. + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 pad[2]; ///< Padding }; }; - } set_report; ///< ::BtdrvHidEventType_SetReport + } set_report; ///< ::BtdrvHidEventType_SetReport struct { union { union { - u8 rawdata[0x290]; ///< Raw data. + u8 rawdata[0x290]; ///< Raw data. struct { - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 pad[2]; ///< Padding - u32 res; ///< 0 = success, non-zero = error. hid-sysmodule only uses the below data when this field is 0. - BtdrvHidData data; ///< \ref BtdrvHidData - u8 pad2[2]; ///< Padding + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 pad[2]; ///< Padding + u32 res; ///< Unknown. hid-sysmodule only uses the below data when this field is 0. + BtdrvHidData report; ///< \ref BtdrvHidData + u8 pad2[2]; ///< Padding }; - } hid_data; ///< Pre-9.0.0 + } v1; ///< [1.0.0-8.1.1] union { - u8 rawdata[0x2C8]; ///< Raw data. + u8 rawdata[0x2C8]; ///< Raw data. struct { - u32 res; ///< 0 = success, non-zero = error. hid-sysmodule only uses the below report when this field is 0. - BtdrvAddress addr; ///< \ref BtdrvAddress - BtdrvHidReport report; ///< \ref BtdrvHidReport + u32 res; ///< Unknown. hid-sysmodule only uses the below report when this field is 0. + BtdrvAddress addr; ///< \ref BtdrvAddress + BtdrvHidReport report; ///< \ref BtdrvHidReport }; - } hid_report; ///< [9.0.0+] + } v9; ///< [9.0.0+] }; - } get_report; ///< ::BtdrvHidEventType_GetReport + } get_report; ///< ::BtdrvHidEventType_GetReport }; } BtdrvHidReportEventInfo; /// The raw sharedmem data for HidReportEventInfo. typedef struct { struct { - u8 type; ///< \ref BtdrvHidEventType + u8 type; ///< \ref BtdrvHidEventType u8 pad[7]; u64 tick; u64 size; } hdr; - union { - struct { - struct { - u8 unused[0x3]; ///< Unused - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 unused2[0x3]; ///< Unused - u16 size; ///< Size of the below data. - u8 data[]; ///< Data. - } v1; ///< Pre-9.0.0 - - struct { - u8 unused[0x4]; ///< Unused - u8 unused_x4; ///< Unused - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 pad; ///< Padding - u16 size; ///< Size of the below data. - u8 data[]; ///< Data. - } v9; ///< [9.0.0+] - } data_report; ///< ::BtdrvHidEventType_Data - - struct { - u8 data[0xC]; ///< Raw data. - } set_report; ///< ::BtdrvHidEventType_SetReport - - struct { - union { - struct { - u8 rawdata[0x290]; ///< Raw data. - } hid_data; ///< Pre-9.0.0 - - struct { - u8 rawdata[0x2C8]; ///< Raw data. - } hid_report; ///< [9.0.0+] - }; - } get_report; ///< ::BtdrvHidEventType_GetReport - } data; + BtdrvHidReportEventInfo data; } BtdrvHidReportEventInfoBufferData; /// Data for \ref btdrvGetAudioEventInfo. The data stored here depends on the \ref BtdrvAudioEventType. @@ -237,7 +298,7 @@ typedef union { /// CircularBuffer typedef struct { Mutex mutex; - void* event_type; ///< Not set with sharedmem. + void* event_type; ///< Not set with sharedmem. u8 data[0x2710]; s32 write_offset; s32 read_offset; @@ -246,6 +307,99 @@ typedef struct { u8 initialized; } BtdrvCircularBuffer; +/// Data for \ref btdrvGetBleManagedEventInfo. The data stored here depends on the \ref BtdrvBleEventType. +typedef struct { + union { + u8 data[0x400]; + + struct { + u32 status; + u8 handle; + u8 registered; + } type0; + + struct { + u32 status; + u32 conn_id; + u32 unk_x8; + u32 unk_xC; + } type2; + + struct { + u32 conn_id; + u16 min_interval; + u16 max_interval; + u16 slave_latency; + u16 timeout_multiplier; + } type3; ///< Connection params? + + struct { + u32 status; + u8 unk_x4; + u8 unk_x5; + u8 unk_x6; + u8 unk_x7; + u32 conn_id; + BtdrvAddress address; + u16 unk_x12; + } type4; ///< Connection status? + + struct { + u32 status; + u8 unk_x4; + u8 unk_x5; + u8 unk_x6; + BtdrvAddress address; + BtdrvBleAdvertisementData adv[10]; + u8 count; + u32 unk_x144; + } type6; ///< Scan result? + + struct { + u32 status; + u32 conn_id; + } type7; + + struct { + u32 status; + u8 interface; + u8 unk_x5; + u16 unk_x6; + u32 unk_x8; + BtdrvGattAttributeUuid svc_uuid; + BtdrvGattAttributeUuid char_uuid; + BtdrvGattAttributeUuid descr_uuid; + u16 size; + u8 data[0x202]; + } type8; ///< Notification? + + struct { + u32 status; + u32 conn_id; + u32 unk_x8; + u8 unk_xC[0x140]; + } type9; + + struct { + u32 status; + u32 conn_id; + u8 unk_x8[0x24]; + u32 unk_x2C; + u8 unk_x30[0x11c]; + } type10; + + struct { + u32 status; + u32 conn_id; + u16 unk_x8; + } type11; + + struct { + u8 unk_x0[0x218]; + } type13; + }; +} BtdrvBleEventInfo; + /// Initialize btdrv. Result btdrvInitialize(void); @@ -282,32 +436,60 @@ Result btdrvDisableBluetooth(void); Result btdrvFinalizeBluetooth(void); /** - * @brief GetAdapterProperties - * @param[out] property \ref BtdrvAdapterProperty + * @brief GetAdapterProperties [1.0.0-11.0.1] + * @param[out] properties \ref BtdrvAdapterPropertyOld */ -Result btdrvGetAdapterProperties(BtdrvAdapterProperty *property); +Result btdrvLegacyGetAdapterProperties(BtdrvAdapterPropertyOld *properties); /** - * @brief GetAdapterProperty + * @brief GetAdapterProperties [12.0.0+] + * @param[out] properties \ref BtdrvAdapterPropertySet + */ +Result btdrvGetAdapterProperties(BtdrvAdapterPropertySet *properties); + +/** + * @brief GetAdapterProperty [1.0.0-11.0.1] * @param[in] type \ref BtdrvBluetoothPropertyType * @param[out] buffer Output buffer, see \ref BtdrvBluetoothPropertyType for the contents. * @param[in] size Output buffer size. */ -Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size); +Result btdrvLegacyGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size); /** - * @brief SetAdapterProperty + * @brief GetAdapterProperty [12.0.0+] + * @param[in] type \ref BtdrvAdapterPropertyType + * @param[in] property \ref BtdrvAdapterProperty + */ +Result btdrvGetAdapterProperty(BtdrvAdapterPropertyType type, BtdrvAdapterProperty *property); + +/** + * @brief SetAdapterProperty [1.0.0-11.0.1] * @param[in] type \ref BtdrvBluetoothPropertyType * @param[in] buffer Input buffer, see \ref BtdrvBluetoothPropertyType for the contents. * @param[in] size Input buffer size. */ -Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size); +Result btdrvLegacySetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size); /** - * @brief This starts Inquiry, the output data will be available via \ref btdrvGetEventInfo. Inquiry will automatically stop in 10.24 seconds. + * @brief SetAdapterProperty [12.0.0+] + * @param[in] type \ref BtdrvAdapterPropertyType + * @param[in] property \ref BtdrvAdapterProperty + */ +Result btdrvSetAdapterProperty(BtdrvAdapterPropertyType type, const BtdrvAdapterProperty *property); + +/** + * @brief StartInquiry [1.0.0-11.0.1]. This starts Inquiry, the output data will be available via \ref btdrvGetEventInfo. Inquiry will automatically stop in 10.24 seconds. * @note This is used by btm-sysmodule. */ -Result btdrvStartInquiry(void); +Result btdrvLegacyStartInquiry(void); + +/** + * @brief StartInquiry [12.0.0+]. This starts Inquiry, the output data will be available via \ref btdrvGetEventInfo. + * @param[in] services Bitfield of allowed services. When -1 the original defaults from pre-12.0.0 are used. + * @param[in] duration Inquiry duration in nanoseconds. + * @note This is used by btm-sysmodule. + */ +Result btdrvStartInquiry(u32 services, s64 duration); /** * @brief This stops Inquiry which was started by \ref btdrvStartInquiry, if it's still active. @@ -338,14 +520,21 @@ Result btdrvRemoveBond(BtdrvAddress addr); Result btdrvCancelBond(BtdrvAddress addr); /** - * @brief RespondToPinRequest + * @brief RespondToPinRequest [1.0.0-11.0.1] * @note The official sysmodule only uses the input \ref BtdrvAddress. * @param[in] addr \ref BtdrvAddress * @param[in] flag Flag * @param[in] pin_code \ref BtdrvBluetoothPinCode - * @param[in] unk Unknown + * @param[in] length Length of pin_code */ -Result btdrvRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 unk); +Result btdrvLegacyRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 length); + +/** + * @brief RespondToPinRequest [12.0.0+] + * @param[in] addr \ref BtdrvAddress + * @param[in] pin_code \ref BtdrvPinCode + */ +Result btdrvRespondToPinRequest(BtdrvAddress addr, const BtdrvPinCode *pin_code); /** * @brief RespondToSspRequest @@ -353,19 +542,19 @@ Result btdrvRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoo * @note This is used by btm-sysmodule. * @param[in] addr \ref BtdrvAddress * @param[in] variant BluetoothSspVariant - * @param[in] flag Whether the request is accepted. - * @param[in] unk Unknown + * @param[in] accept Whether the request is accepted. + * @param[in] passkey Passkey. */ -Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 unk); +Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool accept, u32 passkey); /** * @brief GetEventInfo * @note This is used by btm-sysmodule. * @param[out] buffer Output buffer, see \ref BtdrvEventInfo. * @param[in] size Output buffer size. - * @oaram[out] type Output EventType. + * @param[out] type Output BtdrvEventType. */ -Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type); +Result btdrvGetEventInfo(void* buffer, size_t size, BtdrvEventType *type); /** * @brief InitializeHid @@ -460,7 +649,7 @@ Result btdrvGetHidEventInfo(void* buffer, size_t size, BtdrvHidEventType *type); /** * @brief SetTsi - * @note The response will be available via \ref btdrvGetHidEventInfo. + * @note The response will be available via \ref btdrvGetHidEventInfo ([12.0.0+] \ref btdrvGetEventInfo). * @note This is used by btm-sysmodule. * @param[in] addr \ref BtdrvAddress * @param[in] tsi Tsi: non-value-0xFF to Set, value 0xFF to Exit. See also \ref BtmTsiMode. @@ -469,7 +658,7 @@ Result btdrvSetTsi(BtdrvAddress addr, u8 tsi); /** * @brief EnableBurstMode - * @note The response will be available via \ref btdrvGetHidEventInfo. + * @note The response will be available via \ref btdrvGetHidEventInfo ([12.0.0+] \ref btdrvGetEventInfo). * @note This is used by btm-sysmodule. * @param[in] addr \ref BtdrvAddress * @param[in] flag Flag: true = Set, false = Exit. @@ -478,7 +667,7 @@ Result btdrvEnableBurstMode(BtdrvAddress addr, bool flag); /** * @brief SetZeroRetransmission - * @note The response will be available via \ref btdrvGetHidEventInfo. + * @note The response will be available via \ref btdrvGetHidEventInfo ([12.0.0+] \ref btdrvGetEventInfo). * @note This is used by btm-sysmodule. * @param[in] addr \ref BtdrvAddress * @param[in] report_ids Input buffer containing an array of u8s. @@ -558,7 +747,7 @@ Result btdrvGetLatestPlr(BtdrvPlrList *out); /** * @brief GetPendingConnections - * @note The output data will be available via \ref btdrvGetHidEventInfo. + * @note The output data will be available via \ref btdrvGetHidEventInfo ([12.0.0+] \ref btdrvGetEventInfo). * @note This is used by btm-sysmodule. * @note Only available on [3.0.0+]. */ @@ -885,9 +1074,9 @@ Result btdrvAddGattDescriptor(u8 unk0, const BtdrvGattAttributeUuid *uuid0, cons * @note This is used by btm-sysmodule. * @param[out] buffer Output buffer. 0x400-bytes from state is written here. * @param[in] size Output buffer size. - * @oaram[out] type Output BleEventType. + * @oaram[out] type Output BtdrvBleEventType. */ -Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, u32 *type); +Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, BtdrvBleEventType *type); /** * @brief GetGattFirstCharacteristic @@ -1086,7 +1275,7 @@ Result btdrvSetBleScanParameter(u16 unk0, u16 unk1); /** * @brief MoveToSecondaryPiconet - * @note The response will be available via \ref btdrvGetHidEventInfo. + * @note The response will be available via \ref btdrvGetHidEventInfo ([12.0.0+] \ref btdrvGetEventInfo). * @note Only available on [10.0.0+]. * @param[in] addr \ref BtdrvAddress */ diff --git a/nx/include/switch/services/btdrv_types.h b/nx/include/switch/services/btdrv_types.h index 2feed997..a5fb5803 100644 --- a/nx/include/switch/services/btdrv_types.h +++ b/nx/include/switch/services/btdrv_types.h @@ -1,32 +1,60 @@ /** * @file btdrv_types.h * @brief Bluetooth driver (btdrv) service types (see btdrv.h for the rest). - * @author yellows8 + * @author yellows8, ndeadly * @copyright libnx Authors */ #pragma once #include "../types.h" -/// BluetoothPropertyType +/// BluetoothPropertyType [1.0.0-11.0.1] typedef enum { - BtdrvBluetoothPropertyType_Name = 1, ///< Name. String, max length 0xF8 excluding NUL-terminator. - BtdrvBluetoothPropertyType_Address = 2, ///< \ref BtdrvAddress - BtdrvBluetoothPropertyType_Unknown3 = 3, ///< Only available with \ref btdrvSetAdapterProperty. Unknown, \ref BtdrvAddress. - BtdrvBluetoothPropertyType_ClassOfDevice = 5, ///< 3-bytes, Class of Device. - BtdrvBluetoothPropertyType_FeatureSet = 6, ///< 1-byte, FeatureSet. The default is value 0x68. + BtdrvBluetoothPropertyType_Name = 1, ///< Name. String, max length 0xF8 excluding NUL-terminator. + BtdrvBluetoothPropertyType_Address = 2, ///< \ref BtdrvAddress + BtdrvBluetoothPropertyType_Unknown3 = 3, ///< Only available with \ref btdrvSetAdapterProperty. Unknown, \ref BtdrvAddress. + BtdrvBluetoothPropertyType_ClassOfDevice = 5, ///< 3-bytes, Class of Device. + BtdrvBluetoothPropertyType_FeatureSet = 6, ///< 1-byte, FeatureSet. The default is value 0x68. } BtdrvBluetoothPropertyType; +/// AdapterPropertyType [12.0.0+] +typedef enum { + BtdrvAdapterPropertyType_Address = 0, ///< \ref BtdrvAddress + BtdrvAdapterPropertyType_Name = 1, ///< Name. String, max length 0xF8 excluding NUL-terminator. + BtdrvAdapterPropertyType_ClassOfDevice = 2, ///< 3-bytes, Class of Device. + BtdrvAdapterPropertyType_Unknown3 = 3, ///< Only available with \ref btdrvSetAdapterProperty. Unknown, \ref BtdrvAddress. +} BtdrvAdapterPropertyType; + /// EventType typedef enum { - BtdrvEventType_Unknown0 = 0, ///< Unused - BtdrvEventType_InquiryDevice = 3, ///< Device found during Inquiry. - BtdrvEventType_InquiryStatus = 4, ///< Inquiry status changed. - BtdrvEventType_PairingPinCodeRequest = 5, ///< Pairing PIN code request. - BtdrvEventType_SspRequest = 6, ///< SSP confirm request / SSP passkey notification. - BtdrvEventType_Connection = 7, ///< Connection - BtdrvEventType_BluetoothCrash = 13, ///< BluetoothCrash + ///< BtdrvEventType_* should be used on [12.0.0+] + BtdrvEventType_InquiryDevice = 0, ///< Device found during Inquiry. + BtdrvEventType_InquiryStatus = 1, ///< Inquiry status changed. + BtdrvEventType_PairingPinCodeRequest = 2, ///< Pairing PIN code request. + BtdrvEventType_SspRequest = 3, ///< SSP confirm request / SSP passkey notification. + BtdrvEventType_Connection = 4, ///< Connection + BtdrvEventType_Tsi = 5, ///< SetTsi (\ref btdrvSetTsi) + BtdrvEventType_BurstMode = 6, ///< SetBurstMode (\ref btdrvEnableBurstMode) + BtdrvEventType_SetZeroRetransmission = 7, ///< \ref btdrvSetZeroRetransmission + BtdrvEventType_PendingConnections = 8, ///< \ref btdrvGetPendingConnections + BtdrvEventType_MoveToSecondaryPiconet = 9, ///< \ref btdrvMoveToSecondaryPiconet + BtdrvEventType_BluetoothCrash = 10, ///< BluetoothCrash + + ///< BtdrvEventTypeOld_* should be used on [1.0.0-11.0.1] + BtdrvEventTypeOld_Unknown0 = 0, ///< Unused + BtdrvEventTypeOld_InquiryDevice = 3, ///< Device found during Inquiry. + BtdrvEventTypeOld_InquiryStatus = 4, ///< Inquiry status changed. + BtdrvEventTypeOld_PairingPinCodeRequest = 5, ///< Pairing PIN code request. + BtdrvEventTypeOld_SspRequest = 6, ///< SSP confirm request / SSP passkey notification. + BtdrvEventTypeOld_Connection = 7, ///< Connection + BtdrvEventTypeOld_BluetoothCrash = 13, ///< BluetoothCrash } BtdrvEventType; +/// BtdrvInquiryStatus +typedef enum { + BtdrvInquiryStatus_Stopped = 0, ///< Inquiry stopped. + BtdrvInquiryStatus_Started = 1, ///< Inquiry started. +} BtdrvInquiryStatus; + /// ConnectionEventType typedef enum { BtdrvConnectionEventType_Status = 0, ///< BtdrvEventInfo::connection::status @@ -34,7 +62,7 @@ typedef enum { BtdrvConnectionEventType_Suspended = 2, ///< ACL Link is now Suspended. } BtdrvConnectionEventType; -/// ExtEventType +/// ExtEventType [1.0.0-11.0.1] typedef enum { BtdrvExtEventType_SetTsi = 0, ///< SetTsi (\ref btdrvSetTsi) BtdrvExtEventType_ExitTsi = 1, ///< ExitTsi (\ref btdrvSetTsi) @@ -49,21 +77,41 @@ typedef enum { /// Bit0-1 directly control the HID bluetooth transaction report-type value. /// Bit2-3: these directly control the Parameter Reserved field for SetReport, for GetReport these control the Parameter Reserved and Size bits. typedef enum { - BtdrvBluetoothHhReportType_Other = 0, ///< Other - BtdrvBluetoothHhReportType_Input = 1, ///< Input - BtdrvBluetoothHhReportType_Output = 2, ///< Output - BtdrvBluetoothHhReportType_Feature = 3, ///< Feature + BtdrvBluetoothHhReportType_Other = 0, ///< Other + BtdrvBluetoothHhReportType_Input = 1, ///< Input + BtdrvBluetoothHhReportType_Output = 2, ///< Output + BtdrvBluetoothHhReportType_Feature = 3, ///< Feature } BtdrvBluetoothHhReportType; /// HidEventType typedef enum { - BtdrvHidEventType_Connection = 0, ///< Connection. Only used with \ref btdrvGetHidEventInfo. - BtdrvHidEventType_Data = 4, ///< DATA report on the Interrupt channel. - BtdrvHidEventType_Ext = 7, ///< Response for extensions. Only used with \ref btdrvGetHidEventInfo. - BtdrvHidEventType_SetReport = 8, ///< Response to SET_REPORT. - BtdrvHidEventType_GetReport = 9, ///< Response to GET_REPORT. + ///< BtdrvHidEventType_* should be used on [12.0.0+] + BtdrvHidEventType_Connection = 0, ///< Connection. Only used with \ref btdrvGetHidEventInfo. + BtdrvHidEventType_Data = 1, ///< DATA report on the Interrupt channel. + BtdrvHidEventType_SetReport = 2, ///< Response to SET_REPORT. + BtdrvHidEventType_GetReport = 3, ///< Response to GET_REPORT. + + ///< BtdrvHidEventTypeOld_* should be used on [1.0.0-11.0.1] + BtdrvHidEventTypeOld_Connection = 0, ///< Connection. Only used with \ref btdrvGetHidEventInfo. + BtdrvHidEventTypeOld_Data = 4, ///< DATA report on the Interrupt channel. + BtdrvHidEventTypeOld_Ext = 7, ///< Response for extensions. Only used with \ref btdrvGetHidEventInfo. + BtdrvHidEventTypeOld_SetReport = 8, ///< Response to SET_REPORT. + BtdrvHidEventTypeOld_GetReport = 9, ///< Response to GET_REPORT. } BtdrvHidEventType; +/// HidConnectionStatus [12.0.0+] +typedef enum { + ///< BtdrvHidConnectionStatus_* should be used on [12.0.0+] + BtdrvHidConnectionStatus_Closed = 0, + BtdrvHidConnectionStatus_Opened = 1, + BtdrvHidConnectionStatus_Failed = 2, + + ///< BtdrvHidConnectionStatusOld_* should be used on [1.0.0-11.0.1] + BtdrvHidConnectionStatusOld_Opened = 0, + BtdrvHidConnectionStatusOld_Closed = 2, + BtdrvHidConnectionStatusOld_Failed = 8, +} BtdrvHidConnectionStatus; + /// This determines the u16 data to write into a CircularBuffer. typedef enum { BtdrvFatalReason_Invalid = 0, ///< Only for \ref BtdrvEventInfo: invalid. @@ -71,8 +119,27 @@ typedef enum { BtdrvFatalReason_CommandTimeout = 2, ///< HCI command timeout. BtdrvFatalReason_HardwareError = 3, ///< HCI event HCI_Hardware_Error occurred. BtdrvFatalReason_Enable = 7, ///< Only for \ref BtdrvEventInfo: triggered after enabling bluetooth, depending on the value of a global state field. + BtdrvFatalReason_Audio = 9, ///< [12.0.0+] Only for \ref BtdrvEventInfo: triggered by Audio cmds in some cases. } BtdrvFatalReason; +/// BleEventType +typedef enum { + BtdrvBleEventType_Unknown0 = 0, ///< Unknown. + BtdrvBleEventType_Unknown1 = 1, ///< Unknown. + BtdrvBleEventType_Unknown2 = 2, ///< Unknown. + BtdrvBleEventType_Unknown3 = 3, ///< Unknown. + BtdrvBleEventType_Unknown4 = 4, ///< Unknown. + BtdrvBleEventType_Unknown5 = 5, ///< Unknown. + BtdrvBleEventType_Unknown6 = 6, ///< Unknown. + BtdrvBleEventType_Unknown7 = 7, ///< Unknown. + BtdrvBleEventType_Unknown8 = 8, ///< Unknown. + BtdrvBleEventType_Unknown9 = 9, ///< Unknown. + BtdrvBleEventType_Unknown10 = 10, ///< Unknown. + BtdrvBleEventType_Unknown11 = 11, ///< Unknown. + BtdrvBleEventType_Unknown12 = 12, ///< Unknown. + BtdrvBleEventType_Unknown13 = 13, ///< Unknown. +} BtdrvBleEventType; + /// AudioEventType typedef enum { BtdrvAudioEventType_None = 0, ///< None @@ -95,26 +162,51 @@ typedef struct { u8 address[0x6]; ///< Address } BtdrvAddress; -/// AdapterProperty +/// ClassOfDevice typedef struct { - BtdrvAddress addr; ///< Same as the data for ::BtdrvBluetoothPropertyType_Address. - u8 class_of_device[0x3]; ///< Same as the data for ::BtdrvBluetoothPropertyType_ClassOfDevice. - char name[0xF9]; ///< Same as the data for ::BtdrvBluetoothPropertyType_Name (last byte is not initialized). - u8 feature_set; ///< Set to hard-coded value 0x68 (same as the data for ::BtdrvBluetoothPropertyType_FeatureSet). + u8 class_of_device[0x3]; ///< ClassOfDevice +} BtdrvClassOfDevice; + +/// AdapterProperty [1.0.0-11.0.1] +typedef struct { + BtdrvAddress addr; ///< Same as the data for ::BtdrvBluetoothPropertyType_Address. + BtdrvClassOfDevice class_of_device; ///< Same as the data for ::BtdrvBluetoothPropertyType_ClassOfDevice. + char name[0xF9]; ///< Same as the data for ::BtdrvBluetoothPropertyType_Name (last byte is not initialized). + u8 feature_set; ///< Set to hard-coded value 0x68 (same as the data for ::BtdrvBluetoothPropertyType_FeatureSet). +} BtdrvAdapterPropertyOld; + +/// AdapterProperty [12.0.0+] +typedef struct { + u8 type; ///< \ref BtdrvAdapterPropertyType + u8 size; ///< Data size. + u8 data[0x100]; ///< Data (above size), as specified by the type. } BtdrvAdapterProperty; -/// BluetoothPinCode +/// AdapterPropertySet [12.0.0+] +typedef struct { + BtdrvAddress addr; ///< Same as the data for ::BtdrvBluetoothPropertyType_Address. + BtdrvClassOfDevice class_of_device; ///< Same as the data for ::BtdrvBluetoothPropertyType_ClassOfDevice. + char name[0xF9]; ///< Same as the data for ::BtdrvBluetoothPropertyType_Name. +} BtdrvAdapterPropertySet; + +/// BluetoothPinCode [1.0.0-11.0.1] typedef struct { char code[0x10]; ///< PinCode } BtdrvBluetoothPinCode; -/// HidData, for pre-9.0.0. +/// BtdrvPinCode [12.0.0+] +typedef struct { + char code[0x10]; ///< PinCode + u8 length; ///< Length +} BtdrvPinCode; + +/// HidData [1.0.0-8.1.1] typedef struct { u16 size; ///< Size of data. u8 data[0x280]; ///< Data } BtdrvHidData; -/// HidReport, for [9.0.0+]. +/// HidReport [9.0.0+]. typedef struct { u16 size; ///< Size of data. u8 data[0x2BC]; ///< Data @@ -171,6 +263,12 @@ typedef struct { u8 pad5[3]; ///< Padding } BtdrvBleAdvertisePacketData; +typedef struct { + u8 length; + u8 type; + u8 value[0x1d]; +} BtdrvBleAdvertisementData; + /// BleAdvertiseFilter typedef struct { u8 unk_x0[0x3E]; ///< Unknown diff --git a/nx/source/services/btdrv.c b/nx/source/services/btdrv.c index 191d8b95..8f24fefc 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -173,14 +173,30 @@ Result btdrvFinalizeBluetooth(void) { return _btdrvCmdNoIO(4); } -Result btdrvGetAdapterProperties(BtdrvAdapterProperty *property) { +Result btdrvLegacyGetAdapterProperties(BtdrvAdapterPropertyOld *properties) { + if (hosversionAtLeast(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatch(&g_btdrvSrv, 5, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, - .buffers = { { property, sizeof(*property) } }, + .buffers = { { properties, sizeof(*properties) } }, ); } -Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size) { +Result btdrvGetAdapterProperties(BtdrvAdapterPropertySet *properties) { + if (hosversionBefore(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return serviceDispatch(&g_btdrvSrv, 5, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { properties, sizeof(*properties) } }, + ); +} + +Result btdrvLegacyGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, size_t size) { + if (hosversionAtLeast(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 tmp=type; return serviceDispatchIn(&g_btdrvSrv, 6, tmp, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, @@ -188,7 +204,21 @@ Result btdrvGetAdapterProperty(BtdrvBluetoothPropertyType type, void* buffer, si ); } -Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size) { +Result btdrvGetAdapterProperty(BtdrvAdapterPropertyType type, BtdrvAdapterProperty *property) { + if (hosversionBefore(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u32 tmp=type; + return serviceDispatchIn(&g_btdrvSrv, 6, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out | SfBufferAttr_FixedSize }, + .buffers = { { property, sizeof(*property) } }, + ); +} + +Result btdrvLegacySetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buffer, size_t size) { + if (hosversionAtLeast(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 tmp=type; return serviceDispatchIn(&g_btdrvSrv, 7, tmp, .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, @@ -196,10 +226,36 @@ Result btdrvSetAdapterProperty(BtdrvBluetoothPropertyType type, const void* buff ); } -Result btdrvStartInquiry(void) { +Result btdrvSetAdapterProperty(BtdrvAdapterPropertyType type, const BtdrvAdapterProperty *property) { + if (hosversionBefore(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u32 tmp=type; + return serviceDispatchIn(&g_btdrvSrv, 7, tmp, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In | SfBufferAttr_FixedSize }, + .buffers = { { property, sizeof(*property) } }, + ); +} + +Result btdrvLegacyStartInquiry(void) { + if (hosversionAtLeast(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _btdrvCmdNoIO(8); } +Result btdrvStartInquiry(u32 services, s64 duration) { + if (hosversionBefore(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u32 services; + s64 duration; + } in = { services, duration }; + + return serviceDispatchIn(&g_btdrvSrv, 8, in); +} + Result btdrvStopInquiry(void) { return _btdrvCmdNoIO(9); } @@ -229,29 +285,56 @@ Result btdrvCancelBond(BtdrvAddress addr) { return _btdrvCmdInAddrNoOut(addr, 12); } -Result btdrvRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 unk) { +Result btdrvLegacyRespondToPinRequest(BtdrvAddress addr, bool flag, const BtdrvBluetoothPinCode *pin_code, u8 length) { + if (hosversionAtLeast(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { BtdrvAddress addr; u8 flag; - u8 unk; + u8 length; BtdrvBluetoothPinCode pin_code; - } in = { addr, flag!=0, unk, *pin_code }; + } in = { addr, flag!=0, length, *pin_code }; return serviceDispatchIn(&g_btdrvSrv, 13, in); } -Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 unk) { +Result btdrvRespondToPinRequest(BtdrvAddress addr, const BtdrvPinCode *pin_code) { + if (hosversionBefore(12,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { BtdrvAddress addr; - u8 variant; - u8 flag; - u32 unk; - } in = { addr, variant, flag!=0, unk }; + BtdrvPinCode pin_code; + } in = { addr, *pin_code }; - return serviceDispatchIn(&g_btdrvSrv, 14, in); + return serviceDispatchIn(&g_btdrvSrv, 13, in); } -Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type) { +Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool accept, u32 passkey) { + if (hosversionBefore(12,0,0)) { + const struct { + BtdrvAddress addr; + u8 variant; + u8 accept; + u32 passkey; + } in = { addr, variant, accept!=0, passkey }; + + return serviceDispatchIn(&g_btdrvSrv, 14, in); + } + else { + const struct { + BtdrvAddress addr; + u8 accept; + u8 variant; + u32 passkey; + } in = { addr, accept!=0, variant, passkey }; + + return serviceDispatchIn(&g_btdrvSrv, 14, in); + } +} + +Result btdrvGetEventInfo(void* buffer, size_t size, BtdrvEventType *type) { return _btdrvCmdOutU32OutBuf(buffer, size, type, 15); } @@ -441,22 +524,26 @@ Result btdrvGetHidReportEventInfo(void* buffer, size_t size, BtdrvHidEventType * *type = BtdrvHidEventType_Data; return 0; } - if (*type == BtdrvHidEventType_GetReport) { - if (hosversionBefore(9,0,0)) memcpy(info->get_report.hid_data.rawdata, data_ptr->data.get_report.hid_data.rawdata, sizeof(info->get_report.hid_data.rawdata)); - else memcpy(info->get_report.hid_report.rawdata, data_ptr->data.get_report.hid_report.rawdata, sizeof(info->get_report.hid_report.rawdata)); + bool is_old = hosversionBefore(12,0,0); + if ((is_old && *type == BtdrvHidEventTypeOld_GetReport) || (!is_old && *type == BtdrvHidEventType_GetReport)) { + if (hosversionBefore(9,0,0)) memcpy(info->get_report.v1.rawdata, data_ptr->data.get_report.v1.rawdata, sizeof(info->get_report.v1.rawdata)); + else memcpy(info->get_report.v9.rawdata, data_ptr->data.get_report.v9.rawdata, sizeof(info->get_report.v9.rawdata)); } - else if (*type == BtdrvHidEventType_SetReport) memcpy(info->set_report.data, data_ptr->data.set_report.data, sizeof(info->set_report.data)); - else if (*type == BtdrvHidEventType_Data) { - u16 tmpsize = hosversionBefore(9,0,0) ? data_ptr->data.data_report.v1.size : data_ptr->data.data_report.v9.size; + else if ((is_old && *type == BtdrvHidEventTypeOld_SetReport) || (!is_old && *type == BtdrvHidEventType_SetReport)) memcpy(info->set_report.rawdata, data_ptr->data.set_report.rawdata, sizeof(info->set_report.rawdata)); + else if ((is_old && *type == BtdrvHidEventTypeOld_Data) || (!is_old && *type == BtdrvHidEventType_Data)) { + u16 tmpsize = hosversionBefore(9,0,0) ? data_ptr->data.data_report.v7.report.size : data_ptr->data.data_report.v9.report.size; if (size < 0xE) return MAKERESULT(Module_Libnx, LibnxError_BadInput); if (tmpsize > size-0xE) tmpsize = size-0xE; - info->data_report.unk_x0 = 0; - info->data_report.size = tmpsize; - if (hosversionBefore(9,0,0)) memcpy(info->data_report.data, data_ptr->data.data_report.v1.data, tmpsize); - else memcpy(info->data_report.data, data_ptr->data.data_report.v9.data, tmpsize); + if (hosversionBefore(9,0,0)) info->data_report.v7.report.size = tmpsize; + else { + info->data_report.v9.res = 0; + info->data_report.v9.report.size = tmpsize; + } + if (hosversionBefore(9,0,0)) memcpy(info->data_report.v7.report.data, data_ptr->data.data_report.v7.report.data, tmpsize); + else memcpy(info->data_report.v9.report.data, data_ptr->data.data_report.v9.report.data, tmpsize); - if (hosversionBefore(9,0,0)) memcpy(&info->data_report.addr, &data_ptr->data.data_report.v1.addr, sizeof(BtdrvAddress)); - else memcpy(&info->data_report.addr, &data_ptr->data.data_report.v9.addr, sizeof(BtdrvAddress)); + if (hosversionBefore(9,0,0)) memcpy(&info->data_report.v7.addr, &data_ptr->data.data_report.v7.addr, sizeof(BtdrvAddress)); + else memcpy(&info->data_report.v9.addr, &data_ptr->data.data_report.v9.addr, sizeof(BtdrvAddress)); } else return MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen); // sdknso would Abort here. btdrvCircularBufferFree(g_btdrvCircularBuffer); @@ -873,7 +960,7 @@ Result btdrvAddGattDescriptor(u8 unk0, const BtdrvGattAttributeUuid *uuid0, cons return serviceDispatchIn(&g_btdrvSrv, cmd_id, in); } -Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, u32 *type) { +Result btdrvGetBleManagedEventInfo(void* buffer, size_t size, BtdrvBleEventType *type) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 cmd_id = hosversionBefore(5,1,0) ? 78 : 79; @@ -1106,7 +1193,7 @@ Result btdrvUnregisterGattNotification(u32 connection_handle, bool primary_servi return _btdrvGattNotification(connection_handle, primary_service, id0, id1, cmd_id); } -Result btdrvGetLeHidEventInfo(void* buffer, size_t size, u32 *type) { +Result btdrvGetLeHidEventInfo(void* buffer, size_t size, BtdrvBleEventType *type) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); u32 cmd_id = hosversionBefore(5,1,0) ? 95 : 96;