diff --git a/nx/include/switch/services/btdrv.h b/nx/include/switch/services/btdrv.h index 49e38b57..1d2211d9 100644 --- a/nx/include/switch/services/btdrv.h +++ b/nx/include/switch/services/btdrv.h @@ -21,37 +21,37 @@ typedef struct { } type0; ///< ::BtdrvEventType_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 + 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 + } inquiry_device; ///< ::BtdrvEventType_InquiryDevice struct { - u32 status; ///< Status: 0 = stopped, 1 = started. + BtdrvInquiryStatus status; ///< Status: 0 = stopped, 1 = started. } 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 + 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. + } 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). @@ -72,10 +72,10 @@ typedef struct { 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; ///< Status: 0 = hid connection opened, 2 = hid connection closed, 8 = failed to open hid connection. + } connection; ///< ::BtdrvHidEventType_Connection struct { u32 type; ///< \ref BtdrvExtEventType, controls which data is stored below. @@ -130,25 +130,48 @@ typedef struct { 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 + union { + struct { + struct { + BtdrvAddress addr; + u8 pad[2]; // Todo: check if padding used here + u32 res; + u32 size; + } hdr; + u8 unused[0x3]; ///< Unused + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 unused2[0x3]; ///< Unused + BtdrvHidData report; + } v1; ///< Pre-7.0.0 + + struct { + u8 unused[0x3]; ///< Unused + BtdrvAddress addr; ///< \ref BtdrvAddress + u8 unused2[0x3]; ///< Unused + BtdrvHidData report; + } v7; ///< Pre-9.0.0 + + 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 data[0xC]; ///< Raw data. + u8 rawdata[0xC]; ///< Raw data. struct { - u32 res; ///< 0 = success, non-zero = error. - BtdrvAddress addr; ///< \ref BtdrvAddress - u8 pad[2]; ///< Padding + 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 { @@ -158,21 +181,21 @@ typedef struct { 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 + 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; ///< Pre-9.0.0 union { 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. + 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 }; @@ -187,42 +210,7 @@ typedef struct { 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; /// CircularBuffer @@ -237,6 +225,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; + bool 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); @@ -354,9 +435,9 @@ Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 un * @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. + * @oaram[out] type Output BtdrvEventType. */ -Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type); +Result btdrvGetEventInfo(void* buffer, size_t size, BtdrvEventType *type); /** * @brief InitializeHid @@ -876,9 +957,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 diff --git a/nx/include/switch/services/btdrv_types.h b/nx/include/switch/services/btdrv_types.h index cb68b2fe..94618017 100644 --- a/nx/include/switch/services/btdrv_types.h +++ b/nx/include/switch/services/btdrv_types.h @@ -27,6 +27,12 @@ typedef enum { BtdrvEventType_BluetoothCrash = 13, ///< BluetoothCrash } BtdrvEventType; +/// BtdrvInquiryStatus +typedef enum { + BtdrvInquiryStatus_Stopped = 0, ///< Inquiry started. + BtdrvInquiryStatus_Started = 1, ///< Inquiry stopped. +} BtdrvInquiryStatus; + /// ConnectionEventType typedef enum { BtdrvConnectionEventType_Status = 0, ///< BtdrvEventInfo::connection::status @@ -64,6 +70,13 @@ typedef enum { BtdrvHidEventType_GetReport = 9, ///< Response to GET_REPORT. } BtdrvHidEventType; +/// HidConnectionStatus +typedef enum { + BtdrvHidConnectionStatus_Connected = 0, + BtdrvHidConnectionStatus_Disconnected = 2, + BtdrvHidConnectionStatus_FailedGeneric = 8, +} BtdrvHidConnectionStatus; + /// This determines the u16 data to write into a CircularBuffer. typedef enum { BtdrvFatalReason_Invalid = 0, ///< Only for \ref BtdrvEventInfo: invalid. @@ -73,17 +86,40 @@ typedef enum { BtdrvFatalReason_Enable = 7, ///< Only for \ref BtdrvEventInfo: triggered after enabling bluetooth, depending on the value of a global state field. } 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; + /// Address typedef struct { u8 address[0x6]; ///< Address } BtdrvAddress; +/// ClassOfDevice +typedef struct { + u8 class_of_device[0x3]; ///< ClassOfDevice +} BtdrvClassOfDevice; + /// AdapterProperty 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). + 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). } BtdrvAdapterProperty; /// BluetoothPinCode @@ -154,6 +190,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 56118dd3..fe0769e4 100644 --- a/nx/source/services/btdrv.c +++ b/nx/source/services/btdrv.c @@ -235,7 +235,7 @@ Result btdrvRespondToSspRequest(BtdrvAddress addr, u8 variant, bool flag, u32 un return serviceDispatchIn(&g_btdrvSrv, 14, in); } -Result btdrvGetEventInfo(void* buffer, size_t size, u32 *type) { +Result btdrvGetEventInfo(void* buffer, size_t size, BtdrvEventType *type) { return _btdrvCmdOutU32OutBuf(buffer, size, type, 15); } @@ -426,21 +426,24 @@ Result btdrvGetHidReportEventInfo(void* buffer, size_t size, BtdrvHidEventType * 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)); + 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_SetReport) memcpy(info->set_report.rawdata, data_ptr->data.set_report.rawdata, sizeof(info->set_report.rawdata)); 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; + 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); @@ -857,7 +860,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; @@ -1090,7 +1093,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;