├── Makefile ├── README.md ├── include └── utils.h └── source ├── main.c └── utils.c /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | 10 | include $(DEVKITPPC)/wii_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # INCLUDES is a list of directories containing extra header files 17 | #--------------------------------------------------------------------------------- 18 | TARGET := $(notdir $(CURDIR)) 19 | BUILD := build 20 | SOURCES := source 21 | DATA := data 22 | INCLUDES := include 23 | 24 | #--------------------------------------------------------------------------------- 25 | # options for code generation 26 | #--------------------------------------------------------------------------------- 27 | 28 | CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) 29 | CXXFLAGS = $(CFLAGS) 30 | 31 | LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map 32 | 33 | #--------------------------------------------------------------------------------- 34 | # any extra libraries we wish to link with the project 35 | #--------------------------------------------------------------------------------- 36 | LIBS := -lfat -lwiiuse -lbte -logc -lm 37 | 38 | #--------------------------------------------------------------------------------- 39 | # list of directories containing libraries, this must be the top level containing 40 | # include and lib 41 | #--------------------------------------------------------------------------------- 42 | LIBDIRS := $(PORTLIBS) 43 | 44 | #--------------------------------------------------------------------------------- 45 | # no real need to edit anything past this point unless you need to add additional 46 | # rules for different file extensions 47 | #--------------------------------------------------------------------------------- 48 | ifneq ($(BUILD),$(notdir $(CURDIR))) 49 | #--------------------------------------------------------------------------------- 50 | 51 | export OUTPUT := $(CURDIR)/$(TARGET) 52 | 53 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 54 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 55 | 56 | export DEPSDIR := $(CURDIR)/$(BUILD) 57 | 58 | #--------------------------------------------------------------------------------- 59 | # automatically build a list of object files for our project 60 | #--------------------------------------------------------------------------------- 61 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 62 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 63 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 64 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 65 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 66 | 67 | #--------------------------------------------------------------------------------- 68 | # use CXX for linking C++ projects, CC for standard C 69 | #--------------------------------------------------------------------------------- 70 | ifeq ($(strip $(CPPFILES)),) 71 | export LD := $(CC) 72 | else 73 | export LD := $(CXX) 74 | endif 75 | 76 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 77 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 78 | $(sFILES:.s=.o) $(SFILES:.S=.o) 79 | 80 | #--------------------------------------------------------------------------------- 81 | # build a list of include paths 82 | #--------------------------------------------------------------------------------- 83 | export INCLUDE := $(foreach dir,$(INCLUDES), -iquote $(CURDIR)/$(dir)) \ 84 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 85 | -I$(CURDIR)/$(BUILD) \ 86 | -I$(LIBOGC_INC) 87 | 88 | #--------------------------------------------------------------------------------- 89 | # build a list of library paths 90 | #--------------------------------------------------------------------------------- 91 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 92 | -L$(LIBOGC_LIB) 93 | 94 | export OUTPUT := $(CURDIR)/$(TARGET) 95 | .PHONY: $(BUILD) clean 96 | 97 | #--------------------------------------------------------------------------------- 98 | $(BUILD): 99 | @[ -d $@ ] || mkdir -p $@ 100 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 101 | 102 | #--------------------------------------------------------------------------------- 103 | clean: 104 | @echo clean ... 105 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol 106 | 107 | #--------------------------------------------------------------------------------- 108 | run: $(BUILD) 109 | wiiload $(TARGET).dol 110 | 111 | 112 | #--------------------------------------------------------------------------------- 113 | else 114 | 115 | DEPENDS := $(OFILES:.o=.d) 116 | 117 | #--------------------------------------------------------------------------------- 118 | # main targets 119 | #--------------------------------------------------------------------------------- 120 | $(OUTPUT).dol: $(OUTPUT).elf 121 | $(OUTPUT).elf: $(OFILES) 122 | 123 | #--------------------------------------------------------------------------------- 124 | # This rule links in binary data with the .jpg extension 125 | #--------------------------------------------------------------------------------- 126 | %.jpg.o : %.jpg 127 | #--------------------------------------------------------------------------------- 128 | @echo $(notdir $<) 129 | $(bin2o) 130 | 131 | -include $(DEPENDS) 132 | 133 | #--------------------------------------------------------------------------------- 134 | endif 135 | #--------------------------------------------------------------------------------- 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ds4pair_wii 2 | =========== 3 | 4 | ds4 tool for the Wii 5 | 6 | (requires the lastest version of libogc) 7 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #define SONY_VID 0x054c 5 | #define DS4_PID 0x05c4 6 | #define DS4_2_PID 0x09cc 7 | 8 | #include 9 | #include 10 | 11 | extern int run; 12 | 13 | void init_stuff(); 14 | void init_video(); 15 | void print_bd_addr(struct bd_addr *bdaddr); 16 | void print_mac(uint8_t *mac); 17 | int bte_read_bdaddr_cb(s32 result, void *userdata); 18 | 19 | void find_and_set_mac(); 20 | int config_add_mac(const uint8_t *mac); 21 | int get_bdaddrs(int fd, unsigned char *paired_mac, unsigned char *ds4_mac); 22 | int set_paired_mac(int fd, unsigned char *mac); 23 | int get_link_key(int fd, unsigned char *link_key); 24 | 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "utils.h" 11 | 12 | int main(int argc, char **argv) 13 | { 14 | init_stuff(); 15 | 16 | printf("ds4pair Wii version by xerpi\n"); 17 | printf("Connect a DS4 controller to the USB and press A. Press HOME to exit.\n\n"); 18 | 19 | while(run) { 20 | WPAD_ScanPads(); 21 | u32 pressed = WPAD_ButtonsDown(0); 22 | if (pressed & WPAD_BUTTON_A) { 23 | find_and_set_mac(); 24 | } 25 | if (pressed & WPAD_BUTTON_HOME) run = 0; 26 | VIDEO_WaitVSync(); 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /source/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "utils.h" 8 | 9 | /* 10 | config header: 11 | offset | size | value 12 | 0 | 4 | number of paired devices 13 | 4 | 6 | BT MAC of the 1st device 14 | 4+6*i | 6 | BT MAC of the i-th device 15 | */ 16 | static const char conf_file[] ATTRIBUTE_ALIGN(32) = "/shared2/sys/ds4wiibt.dat"; 17 | 18 | int run = 1; 19 | static int bd_addr_read = 0; 20 | static int heap_id = -1; 21 | static void *xfb = NULL; 22 | static GXRModeObj *rmode = NULL; 23 | 24 | static void button_cb() 25 | { 26 | run = 0; 27 | } 28 | 29 | void init_stuff() 30 | { 31 | SYS_SetResetCallback(button_cb); 32 | SYS_SetPowerCallback(button_cb); 33 | fatInitDefault(); 34 | init_video(); 35 | WPAD_Init(); 36 | heap_id = iosCreateHeap(4096); 37 | } 38 | 39 | void find_and_set_mac() 40 | { 41 | struct bd_addr bdaddr; 42 | bd_addr_read = 0; 43 | 44 | BTE_ReadBdAddr(&bdaddr, bte_read_bdaddr_cb); 45 | 46 | //Wait until we get the callback... 47 | while (!bd_addr_read) usleep(1000); 48 | 49 | //Find the DS4 controller 50 | usb_device_entry dev_entry[8]; 51 | unsigned char dev_count; 52 | if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0) { 53 | printf("Error getting USB device list.\n"); return; 54 | } 55 | 56 | int i; 57 | usb_device_entry *de; 58 | for (i = 0; i < dev_count; ++i) { 59 | de = &dev_entry[i]; 60 | 61 | if (de->vid == SONY_VID && ((de->pid == DS4_PID) || (de->pid == DS4_2_PID))) { 62 | printf("DS4 found.\n"); 63 | 64 | int fd; 65 | if (USB_OpenDevice(de->device_id, de->vid, de->pid, &fd) < 0) { 66 | printf("Could not open the DS4.\n"); return; 67 | } 68 | 69 | printf("Wii local BD MAC: "); 70 | print_mac(bdaddr.addr); 71 | printf("\n"); 72 | 73 | unsigned char paired[6] = {0}, 74 | ds4_mac[6] ATTRIBUTE_ALIGN(32) = {0}; 75 | get_bdaddrs(fd, paired, ds4_mac); 76 | printf("Controller's bluetooth MAC address: "); 77 | print_mac(ds4_mac); 78 | printf("\n"); 79 | printf("\nCurrent controller paired address: "); 80 | print_mac(paired); 81 | printf("\n"); 82 | 83 | //Write the MAC to the NAND 84 | if (config_add_mac(ds4_mac)) { 85 | printf("DS4 MAC added to the config file!\n"); 86 | } 87 | 88 | struct bd_addr bd2; 89 | memcpy(bd2.addr, paired, sizeof(uint8_t) * 6); 90 | if (bd_addr_cmp(&bdaddr, &bd2)) { 91 | printf("\n\nAddress is already set! Press HOME to exit.\n"); 92 | return; 93 | } 94 | 95 | printf("\nSetting the pair address..."); 96 | uint8_t *mac2 = bdaddr.addr; 97 | set_paired_mac(fd, mac2); 98 | u8 mac[6] = {0}; 99 | get_bdaddrs(fd, mac, NULL); 100 | printf("\nController's pair address set to: "); 101 | print_mac(mac); 102 | 103 | memcpy(bd2.addr, mac2, sizeof(uint8_t) * 6); 104 | if (bd_addr_cmp(&bdaddr, &bd2)) { 105 | printf("\n\nAddress set correctly! Press HOME to exit.\n"); 106 | } else { 107 | printf("\n\nPair MAC Address could not be set correctly.\n"); 108 | } 109 | 110 | USB_CloseDevice(&fd); 111 | return; 112 | } 113 | } 114 | printf("No controller found on USB busses.\n"); 115 | } 116 | 117 | //Deletes the config file and adds this mac 118 | int config_add_mac(const uint8_t *mac) 119 | { 120 | ISFS_Initialize(); 121 | int fd = ISFS_Open(conf_file, ISFS_OPEN_RW); 122 | if (fd >= 0) { 123 | ISFS_Close(fd); 124 | ISFS_Delete(conf_file); 125 | } 126 | printf("Creating config file... "); 127 | int ret = ISFS_CreateFile(conf_file, 0, ISFS_OPEN_RW, ISFS_OPEN_RW, ISFS_OPEN_RW); 128 | if (ret < 0) { 129 | printf("Error creating \"%s\" : %d\n", conf_file, ret); 130 | return -1; 131 | } 132 | printf("done!\n"); 133 | fd = ISFS_Open(conf_file, ISFS_OPEN_RW); 134 | ISFS_Seek(fd, 0, SEEK_SET); 135 | int n = ISFS_Write(fd, mac, 6); 136 | ISFS_Close(fd); 137 | ISFS_Deinitialize(); 138 | return (n == 6); 139 | } 140 | 141 | int set_paired_mac(int fd, unsigned char *mac) 142 | { 143 | u8 ATTRIBUTE_ALIGN(32) buf[] = { 144 | 0x13, 145 | mac[5], mac[4], mac[3], mac[2], mac[1], mac[0], 146 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 147 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 148 | }; 149 | return USB_WriteCtrlMsg(fd, 150 | USB_REQTYPE_INTERFACE_SET, 151 | USB_REQ_SETCONFIG, 152 | (USB_REPTYPE_FEATURE<<8) | 0x13, 153 | 0, 154 | sizeof(buf), 155 | buf); 156 | } 157 | 158 | int get_link_key(int fd, unsigned char *link_key) 159 | { 160 | u8 ATTRIBUTE_ALIGN(32) buf[0x10]; 161 | int ret = USB_ReadCtrlMsg(fd, 162 | USB_REQTYPE_INTERFACE_GET, 163 | USB_REQ_CLEARFEATURE, 164 | (USB_REPTYPE_FEATURE<<8) | 0x13, 165 | 0, 166 | sizeof(buf), 167 | buf); 168 | 169 | int i; 170 | for(i = 0; i < ret; i++) { 171 | link_key[i] = buf[i]; 172 | } 173 | return ret; 174 | } 175 | 176 | int get_bdaddrs(int fd, unsigned char *paired_mac, unsigned char *ds4_mac) 177 | { 178 | u8 ATTRIBUTE_ALIGN(32) buf[0x10]; 179 | int ret = USB_ReadCtrlMsg(fd, 180 | USB_REQTYPE_INTERFACE_GET, 181 | USB_REQ_CLEARFEATURE, 182 | (USB_REPTYPE_FEATURE<<8) | 0x12, 183 | 0, 184 | sizeof(buf), 185 | buf); 186 | 187 | if (paired_mac) { 188 | paired_mac[0] = buf[15]; 189 | paired_mac[1] = buf[14]; 190 | paired_mac[2] = buf[13]; 191 | paired_mac[3] = buf[12]; 192 | paired_mac[4] = buf[11]; 193 | paired_mac[5] = buf[10]; 194 | } 195 | if (ds4_mac) { 196 | ds4_mac[0] = buf[6]; 197 | ds4_mac[1] = buf[5]; 198 | ds4_mac[2] = buf[4]; 199 | ds4_mac[3] = buf[3]; 200 | ds4_mac[4] = buf[2]; 201 | ds4_mac[5] = buf[1]; 202 | } 203 | 204 | return ret; 205 | } 206 | 207 | 208 | int bte_read_bdaddr_cb(s32 result, void *userdata) 209 | { 210 | bd_addr_read = 1; 211 | return 1; 212 | } 213 | 214 | void print_mac(uint8_t *mac) 215 | { 216 | printf("%02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); 217 | } 218 | 219 | void init_video() 220 | { 221 | VIDEO_Init(); 222 | rmode = VIDEO_GetPreferredMode(NULL); 223 | xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); 224 | console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); 225 | VIDEO_Configure(rmode); 226 | VIDEO_SetNextFramebuffer(xfb); 227 | VIDEO_SetBlack(FALSE); 228 | VIDEO_Flush(); 229 | VIDEO_WaitVSync(); 230 | if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); 231 | printf("\x1b[1;0H"); 232 | } 233 | --------------------------------------------------------------------------------