GCC Code Coverage Report


Directory: main/
File: bluetooth/hidp/wii.c
Date: 2025-10-04 14:03:00
Exec Total Coverage
Lines: 57 95 60.0%
Functions: 7 8 87.5%
Branches: 11 31 35.5%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2019-2024, Jacques Gagnon
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <stdio.h>
7 #include "bluetooth/host.h"
8 #include "wii.h"
9
10 enum {
11 WII_EXT_STATE_SET_INIT0 = 0,
12 WII_EXT_STATE_SET_INIT1,
13 WII_EXT_STATE_GET_TYPE,
14 WII_EXT_STATE_SET_8BIT,
15 WII_EXT_STATE_GET_8BIT,
16 };
17
18 struct bt_wii_ext_type {
19 uint8_t ext_type[6];
20 uint32_t subtype;
21 };
22
23 static const struct bt_hidp_wii_rep_mode wii_rep_conf = {
24 BT_HIDP_WII_CONTINUOUS,
25 BT_HIDP_WII_CORE_ACC_EXT,
26 };
27
28 static const struct bt_hidp_wii_wr_mem wii_ext_init0 = {
29 BT_HIDP_WII_REG,
30 {0xA4, 0x00, 0xF0},
31 0x01,
32 {0x55},
33 };
34
35 static const struct bt_hidp_wii_wr_mem wii_ext_init1 = {
36 BT_HIDP_WII_REG,
37 {0xA4, 0x00, 0xFB},
38 0x01,
39 {0x00},
40 };
41
42 static const struct bt_hidp_wii_wr_mem wii_ext_8bit = {
43 BT_HIDP_WII_REG,
44 {0xA4, 0x00, 0xFE},
45 0x01,
46 {0x03},
47 };
48
49 static const struct bt_hidp_wii_rd_mem wii_ext_type = {
50 BT_HIDP_WII_REG,
51 {0xA4, 0x00, 0xFA},
52 0x0600,
53 };
54
55 static const struct bt_wii_ext_type bt_wii_ext_type[] = {
56 {{0x00, 0x00, 0xA4, 0x20, 0x00, 0x00}, BT_WII_NUNCHUCK},
57 {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x01}, BT_WII_CLASSIC},
58 {{0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}, BT_WII_CLASSIC_PRO},
59 {{0x00, 0x00, 0xA4, 0x20, 0x03, 0x01}, BT_WII_CLASSIC_8BIT},
60 {{0x01, 0x00, 0xA4, 0x20, 0x03, 0x01}, BT_WII_CLASSIC_PRO_8BIT},
61 {{0x00, 0x00, 0xA4, 0x20, 0x01, 0x20}, BT_WIIU_PRO},
62 };
63
64 static uint32_t bt_get_subtype_from_wii_ext(const uint8_t* ext_type);
65 static void bt_hid_cmd_wii_set_rep_mode(struct bt_dev *device, void *report);
66 static void bt_hid_cmd_wii_read(struct bt_dev *device, void *report);
67 static void bt_hid_cmd_wii_write(struct bt_dev *device, void *report);
68
69 10 static uint32_t bt_get_subtype_from_wii_ext(const uint8_t* ext_type) {
70
1/2
✓ Branch 0 (6→3) taken 30 times.
✗ Branch 1 (6→7) not taken.
30 for (uint32_t i = 0; i < sizeof(bt_wii_ext_type)/sizeof(*bt_wii_ext_type); i++) {
71
2/2
✓ Branch 0 (3→4) taken 10 times.
✓ Branch 1 (3→5) taken 20 times.
30 if (memcmp(ext_type, bt_wii_ext_type[i].ext_type, sizeof(bt_wii_ext_type[0].ext_type)) == 0) {
72 10 return bt_wii_ext_type[i].subtype;
73 }
74 }
75 return BT_SUBTYPE_DEFAULT;
76 }
77
78 4 static void bt_wii_exec_next_state(struct bt_dev *device) {
79
1/6
✗ Branch 0 (2→3) not taken.
✗ Branch 1 (2→5) not taken.
✗ Branch 2 (2→7) not taken.
✓ Branch 3 (2→9) taken 4 times.
✗ Branch 4 (2→11) not taken.
✗ Branch 5 (2→13) not taken.
4 switch(device->hid_state) {
80 case WII_EXT_STATE_SET_INIT0:
81 bt_hid_cmd_wii_write(device, (void *)&wii_ext_init0);
82 break;
83 case WII_EXT_STATE_SET_INIT1:
84 bt_hid_cmd_wii_write(device, (void *)&wii_ext_init1);
85 break;
86 case WII_EXT_STATE_GET_TYPE:
87 bt_hid_cmd_wii_read(device, (void *)&wii_ext_type);
88 break;
89 4 case WII_EXT_STATE_SET_8BIT:
90 4 bt_hid_cmd_wii_write(device, (void *)&wii_ext_8bit);
91 4 break;
92 case WII_EXT_STATE_GET_8BIT:
93 bt_hid_cmd_wii_read(device, (void *)&wii_ext_type);
94 break;
95 default:
96 break;
97 }
98 4 }
99
100 19 static void bt_hid_cmd_wii_set_rep_mode(struct bt_dev *device, void *report) {
101 19 struct bt_hidp_wii_rep_mode *wii_rep_mode = (struct bt_hidp_wii_rep_mode *)bt_hci_pkt_tmp.hidp_data;
102 19 printf("# %s\n", __FUNCTION__);
103
104 19 memcpy((void *)wii_rep_mode, report, sizeof(*wii_rep_mode));
105
106 19 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_WII_REP_MODE, sizeof(*wii_rep_mode));
107 19 }
108
109 static void bt_hid_cmd_wii_read(struct bt_dev *device, void *report) {
110 struct bt_hidp_wii_rd_mem *wii_rd_mem = (struct bt_hidp_wii_rd_mem *)bt_hci_pkt_tmp.hidp_data;
111 printf("# %s\n", __FUNCTION__);
112
113 memcpy((void *)wii_rd_mem, report, sizeof(*wii_rd_mem));
114
115 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_WII_RD_MEM, sizeof(*wii_rd_mem));
116 }
117
118 4 static void bt_hid_cmd_wii_write(struct bt_dev *device, void *report) {
119 4 struct bt_hidp_wii_wr_mem *wii_wr_mem = (struct bt_hidp_wii_wr_mem *)bt_hci_pkt_tmp.hidp_data;
120 4 printf("# %s\n", __FUNCTION__);
121
122 4 memcpy((void *)wii_wr_mem, report, sizeof(*wii_wr_mem));
123
124 4 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_WII_WR_MEM, sizeof(*wii_wr_mem));
125 4 }
126
127 20 void bt_hid_cmd_wii_set_feedback(struct bt_dev *device, void *report) {
128 20 struct bt_hidp_wii_conf *wii_conf = (struct bt_hidp_wii_conf *)bt_hci_pkt_tmp.hidp_data;
129 //printf("# %s\n", __FUNCTION__);
130
131 20 memcpy((void *)wii_conf, report, sizeof(*wii_conf));
132
133 20 bt_hid_cmd(device->acl_handle, device->intr_chan.dcid, BT_HIDP_DATA_OUT, BT_HIDP_WII_LED_REPORT, sizeof(*wii_conf));
134 20 }
135
136 13 void bt_hid_wii_init(struct bt_dev *device) {
137 13 struct bt_data *bt_data = &bt_adapter.data[device->ids.id];
138 13 struct bt_hidp_wii_conf *set_conf = (struct bt_hidp_wii_conf *)bt_data->base.output;
139 13 set_conf->conf = bt_hid_led_dev_id_map[device->ids.out_idx] << 4;
140
141 13 struct bt_hidp_wii_conf wii_conf = {.conf = (bt_hid_led_dev_id_map[device->ids.out_idx] << 4)};
142 13 printf("# %s\n", __FUNCTION__);
143
144 13 bt_hid_cmd_wii_set_feedback(device, (void *)&wii_conf);
145 13 bt_hid_cmd_wii_set_rep_mode(device, (void *)&wii_rep_conf);
146
147 13 atomic_set_bit(&device->flags, BT_DEV_HID_INIT_DONE);
148 13 }
149
150 225 void bt_hid_wii_hdlr(struct bt_dev *device, struct bt_hci_pkt *bt_hci_acl_pkt, uint32_t len) {
151 225 uint32_t hidp_data_len = len - (BT_HCI_H4_HDR_SIZE + BT_HCI_ACL_HDR_SIZE
152 + sizeof(struct bt_l2cap_hdr) + sizeof(struct bt_hidp_hdr));
153
154
1/2
✓ Branch 0 (2→3) taken 225 times.
✗ Branch 1 (2→27) not taken.
225 switch (bt_hci_acl_pkt->sig_hdr.code) {
155 225 case BT_HIDP_DATA_IN:
156
2/5
✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→10) taken 10 times.
✗ Branch 2 (3→18) not taken.
✓ Branch 3 (3→25) taken 215 times.
✗ Branch 4 (3→27) not taken.
225 switch (bt_hci_acl_pkt->hidp_hdr.protocol) {
157 case BT_HIDP_WII_STATUS:
158 {
159 struct bt_hidp_wii_status *status = (struct bt_hidp_wii_status *)bt_hci_acl_pkt->hidp_data;
160 printf("# BT_HIDP_WII_STATUS\n");
161 if (device->ids.subtype != BT_WIIU_PRO) {
162 bt_type_update(device->ids.id, BT_WII, BT_SUBTYPE_DEFAULT);
163 if (status->flags & BT_HIDP_WII_FLAGS_EXT_CONN) {
164 device->hid_state = WII_EXT_STATE_SET_INIT0;
165 bt_hid_cmd_wii_write(device, (void *)&wii_ext_init0);
166 }
167 else {
168 bt_hid_cmd_wii_set_rep_mode(device, (void *)&wii_rep_conf);
169 }
170 }
171 break;
172 }
173 10 case BT_HIDP_WII_RD_DATA:
174 {
175 10 struct bt_hidp_wii_rd_data *rd_data = (struct bt_hidp_wii_rd_data *)bt_hci_acl_pkt->hidp_data;
176 10 uint32_t subtype = bt_get_subtype_from_wii_ext(rd_data->data);
177 10 printf("# BT_HIDP_WII_RD_DATA\n");
178
1/2
✓ Branch 0 (11→12) taken 10 times.
✗ Branch 1 (11→13) not taken.
10 if (subtype > BT_SUBTYPE_DEFAULT) {
179 10 bt_type_update(device->ids.id, BT_WII, subtype);
180 }
181 10 printf("# dev: %ld wii ext: %ld\n", device->ids.id, device->ids.subtype);
182
183 #ifndef CONFIG_BLUERETRO_TEST_FALLBACK_REPORT
184
3/4
✓ Branch 0 (14→15) taken 4 times.
✓ Branch 1 (14→17) taken 6 times.
✓ Branch 2 (15→16) taken 4 times.
✗ Branch 3 (15→17) not taken.
10 if ((subtype == BT_WII_CLASSIC || subtype == BT_WII_CLASSIC_PRO) && device->hid_state < WII_EXT_STATE_SET_8BIT) {
185 4 device->hid_state = WII_EXT_STATE_SET_8BIT;
186 4 bt_wii_exec_next_state(device);
187 }
188 else
189 #endif
190 {
191 6 bt_hid_cmd_wii_set_rep_mode(device, (void *)&wii_rep_conf);
192 }
193 break;
194 }
195 case BT_HIDP_WII_ACK:
196 {
197 struct bt_hidp_wii_ack *ack = (struct bt_hidp_wii_ack *)bt_hci_acl_pkt->hidp_data;
198 printf("# BT_HIDP_WII_ACK\n");
199 if (ack->err) {
200 printf("# dev: %ld ack err: 0x%02X\n", device->ids.id, ack->err);
201 bt_wii_exec_next_state(device);
202 }
203 else {
204 device->hid_state++;
205 switch(ack->report) {
206 case BT_HIDP_WII_WR_MEM:
207 bt_wii_exec_next_state(device);
208 break;
209 }
210 }
211 break;
212 }
213 215 case BT_HIDP_WII_CORE_ACC_EXT:
214 {
215 215 bt_host_bridge(device, bt_hci_acl_pkt->hidp_hdr.protocol, bt_hci_acl_pkt->hidp_data, hidp_data_len);
216 215 break;
217 }
218 }
219 break;
220 }
221 225 }
222