some testcode for bluetooth stuff, thanks to marcan.
[ppcskel.git] / usb / blehwm.c
1 /* thanks to marcan for this! */
2 /* see @ http://www.youtube.com/watch?v=uqLrD8beikg */
3 #define USB_IOCTL_CTRLMSG 0
4 #define USB_IOCTL_BULKMSG 1
5 #define USB_IOCTL_INTRMSG 2
6 #define USB_IOCTL_GET_DEVICE_LIST 0xC
7
8 #define USB_CREQ_H2D 0x00
9 #define USB_CREQ_D2H 0x80
10 #define USB_CREQ_STANDARD 0x00
11 #define USB_CREQ_CLASS 0x20
12 #define USB_CREQ_VENDOR 0x40
13 #define USB_CREQ_DEVICE 0x00
14 #define USB_CREQ_INTERFACE 0x01
15 #define USB_CREQ_ENDPOINT 0x02
16 #define USB_CREQ_OTHER 0x03
17
18 #define SWAB16(x) ((((x)&0xFF)<<8)|((x)>>8))
19
20 #define ALIGNED(n) __attribute__((aligned(n)))
21
22
23 int usb_ctrl_msg(int fd, u8 bmRequestType, u8 bRequest, u16 wValue, u16 wIndex, void* payload, u16 wLength)
24 {
25 //      printf("USB control: %x %x %x %x %x LEN %x BUF %p\n", fd, bmRequestType, bRequest, wValue, wIndex, wLength, payload);
26         return IOS_Ioctlv_Fmt(fd, USB_IOCTL_CTRLMSG, "bbhhhb:d", bmRequestType, bRequest, SWAB16(wValue), SWAB16(wIndex), SWAB16(wLength), 0, payload, wLength);
27 }
28
29 // the following two functions work for both reads and writes!
30 int usb_intr_msg(int fd, u8 bEndpoint, void* payload, u16 wLength)
31 {
32 //      printf("USB interrupt: EP %x LEN %x BUF %p\n", bEndpoint, wLength, payload);
33         return IOS_Ioctlv_Fmt(fd, USB_IOCTL_INTRMSG, "bh:d", bEndpoint, wLength, payload, wLength);
34 }
35
36 int usb_bulk_msg(int fd, u8 bEndpoint, void* payload, u16 wLength)
37 {
38 //      printf("USB bulk: EP %x LEN %x BUF %p\n", bEndpoint, wLength, payload);
39         return IOS_Ioctlv_Fmt(fd, USB_IOCTL_BULKMSG, "bh:d", bEndpoint, wLength, payload, wLength);
40 }
41
42 int usb_bulk_msg_async(int fd, u8 bEndpoint, void* payload, u16 wLength, ipccallback ipc_cb,void *usrdata)
43 {
44 //      printf("USB bulk: EP %x LEN %x BUF %p\n", bEndpoint, wLength, payload);
45         return IOS_IoctlvAsync_Fmt(fd, USB_IOCTL_BULKMSG, ipc_cb, usrdata, "bh:d", bEndpoint, wLength, payload, wLength);
46 }
47
48 int usb_get_device_list(int fd, u8 type)
49 {
50         int ret;
51         static u8 rcnt[0x100] ALIGNED(0x20);
52         static u8 buf[0x80] ALIGNED(0x20);
53         memset(buf,0,sizeof(buf));
54         rcnt[0] = 0xFF;
55         ret = IOS_Ioctlv_Fmt(fd, USB_IOCTL_GET_DEVICE_LIST, "bb:bd", sizeof(buf)>>3, type, rcnt, buf, sizeof(buf));
56         printf("USB dev list %d ret %d rcnt %d data:\n",type,ret,rcnt[0]);
57         hexdump(buf,8);
58         return ret;
59 }
60
61 #define EP_CONTROL 0x00
62 #define EP_EVENTS 0x81
63 #define EP_ACL_OUT 0x02
64 #define EP_ACL_IN 0x82
65
66 #define HCI_G_LINKCONTROL 1
67 #define HCI_G_LINKPOLICY 2
68 #define HCI_G_CONTROLLER 3
69 #define HCI_G_INFORMATIONAL 4
70 #define HCI_G_STATUS 5
71 #define HCI_G_TESTING 6
72
73 #define HCI_C_RESET 0x0003
74 #define HCI_LC_CONNECT 0x0005
75
76 #define HCI_PKTTYPE_DM1 0x0008
77 #define HCI_PSRM_R2 2
78 #define HCI_CLKOFF_INVALID 0
79 #define HCI_NO_ROLESWITCH 0
80
81 #define HCI_EV_CONNECTION_COMPLETE 0x03
82
83 int bt_HCI_command(int fd, int ogf, int ocf, u8 *parameters, u8 parmlength) {
84         int opcode;
85         static u8 buffer[0x103] ALIGNED(0x40);
86         opcode = (ocf&0x3FF) | ((ogf &0x3F)<<10);
87         buffer[0] = opcode&0xFF;
88         buffer[1] = opcode>>8;
89         buffer[2] = parmlength;
90         
91         if(parameters && parmlength) {
92                 memcpy (&buffer[3], parameters, parmlength);
93         } else {
94                 parmlength = 0; //make sure we don't pass around junk
95         }
96         
97         return usb_ctrl_msg(fd, USB_CREQ_H2D|USB_CREQ_CLASS|USB_CREQ_DEVICE, 0, 0, 0, buffer, parmlength+3);
98 }
99
100 typedef struct {
101         u8 event_code;
102         u8 data_length;
103         u8 *data;
104 } HCI_Event;
105
106 typedef struct {
107         u16 chnd;
108         int pb,bc;
109         u16 data_length;
110         u8 *data;
111 } HCI_ACL_Data;
112
113 int bt_HCI_recv_event(int fd, HCI_Event *ev) {
114
115         static u8 buffer[0x102] ALIGNED(0x40);
116         int res;
117         
118         res = usb_intr_msg(fd, EP_EVENTS, buffer, sizeof(buffer));
119         ev->event_code = buffer[0];
120         ev->data_length = buffer[1];
121         ev->data = &buffer[2];
122         printf("HCI event [%d]: Code 0x%x, length %d, data:\n",res,ev->event_code, ev->data_length);
123         hexdump(ev->data, ev->data_length);
124         return res;
125 }
126
127 int bt_HCI_reset(int fd) {
128         
129         return bt_HCI_command(fd, HCI_G_CONTROLLER, HCI_C_RESET, NULL, 0);
130 }
131
132 int bt_HCI_connect(int fd, u8 *bdaddr, u16 pkt_types, u8 psrm, u16 clkoff, u8 roleswitch) {
133         
134         static u8 data[13];
135         int i;
136         for(i=0;i<6;i++) data[i] = bdaddr[5-i];
137         data[6] = pkt_types & 0xFF;
138         data[7] = pkt_types >> 8;
139         data[8] = psrm;
140         data[9] = 0; //reserved
141         data[10] = clkoff & 0xFF;
142         data[11] = clkoff >> 8;
143         data[12] = roleswitch;
144         
145         return bt_HCI_command(fd, HCI_G_LINKCONTROL, HCI_LC_CONNECT, data, sizeof(data));
146 }
147
148 int bt_HCI_send_ACL(int fd, u16 chnd, int pb, int bc, u16 length, u8 *data) {
149         static u8 buffer[0x100] ALIGNED(0x40);
150         printf("<ACL chnd %04x pb %d bc %d len %d data:\n",chnd,pb,bc,length);
151         hexdump(data,length);
152         chnd &= 0x0FFF;
153         chnd |= pb<<12;
154         chnd |= bc<<14;
155         memcpy(&buffer[4],data,length);
156         buffer[0] = chnd & 0xFF;
157         buffer[1] = chnd >> 8;
158         buffer[2] = length & 0xFF;
159         buffer[3] = length >>8;
160         return usb_bulk_msg(fd, EP_ACL_OUT, buffer, length+4);
161 }
162
163 int bt_HCI_recv_ACL(int fd, HCI_ACL_Data *acl) {
164         static u8 buffer[0x40] ALIGNED(0x40);
165         int res;
166         
167         res = usb_bulk_msg(fd, EP_ACL_IN, buffer, sizeof(buffer));
168         acl->chnd = buffer[0] | (buffer[1]<<8);
169         acl->pb = (acl->chnd & 0x3000)>>12;
170         acl->bc = (acl->chnd & 0xC000)>>14;
171         acl->chnd &= 0x0FFF;
172         acl->data_length = buffer[2] | (buffer[3]<<8);
173         acl->data = &buffer[4];
174         printf(">ACL [%d]: chnd %04x pb %d bc %d len %d data:\n",res,acl->chnd, acl->pb, acl->bc, acl->data_length);
175         hexdump(acl->data, acl->data_length);
176         return res;
177 }
178
179 static volatile int flag = 0;
180 static volatile int res;
181
182 s32 _bt_cb(int r, void *data) {
183         res = r;
184         flag = 1;
185         return 0;
186 }
187
188 int bt_HCI_recv_ACL_async(int fd, HCI_ACL_Data *acl) {
189         static u8 buffer[0x40] ALIGNED(0x40);
190         int res;
191         flag = 0;
192         res = usb_bulk_msg_async(fd, EP_ACL_IN, buffer, sizeof(buffer), _bt_cb, NULL);
193         while(!flag) {
194                 VIDEO_WaitVSync();
195                 PAD_ScanPads();
196                 int buttonsDown = PAD_ButtonsHeld(0);
197                 if( (buttonsDown & PAD_TRIGGER_Z) && (buttonsDown & PAD_BUTTON_START)) {
198                         loader();
199                 }
200         }
201         flag = 0;
202         acl->chnd = buffer[0] | (buffer[1]<<8);
203         acl->pb = (acl->chnd & 0x3000)>>12;
204         acl->bc = (acl->chnd & 0xC000)>>14;
205         acl->chnd &= 0x0FFF;
206         acl->data_length = buffer[2] | (buffer[3]<<8);
207         acl->data = &buffer[4];
208         printf(">ACL [%d]: chnd %04x pb %d bc %d len %d data:\n",res,acl->chnd, acl->pb, acl->bc, acl->data_length);
209         hexdump(acl->data, acl->data_length);
210         return res;
211 }
212
213 int bt_L2CAP_send(int fd, u16 chnd, u16 cid, u16 length, u8 *data)
214 {
215         static u8 buffer[0x1000] ALIGNED(0x20);
216         memcpy(&buffer[4],data,length);
217         buffer[0] = length & 0xFF;
218         buffer[1] = length >> 8;
219         buffer[2] = cid & 0xFF;
220         buffer[3] = cid >> 8;
221         return bt_HCI_send_ACL(fd, chnd, 2, 0, length+4, buffer);
222 }
223
224 void checkAndReload(void) {
225         PAD_ScanPads();
226         int buttonsDown = PAD_ButtonsHeld(0);
227         if( (buttonsDown & PAD_TRIGGER_Z) && (buttonsDown & PAD_BUTTON_START)) {
228                 loader();
229         }
230 }
231 ------------
232         
233         /*
234         // Bluetooth HCI reset command
235         memcpy(buf,"\x03\x0c\x00",3);
236         // Bluetooth request to control endpoint
237         ret = IOS_Ioctlv_Fmt(btm_fd, 0, "bbhhhb:d", 0x20, 0, 0, 0, 0x0300, 0, buf, 3);
238         printf("IOS ioctlv USB: %d\n",ret);
239         */
240         /*
241         if(btm_fd>0) {
242                 ret = bt_HCI_reset(btm_fd);
243                 printf("HCI reset to %d returned %d\n",btm_fd,ret);
244                 ret = bt_HCI_recv_event(btm_fd, &hciev);
245                 ret = bt_HCI_connect(btm_fd, (u8*)"\x00\x17\xAB\x33\x37\x65", HCI_PKTTYPE_DM1, HCI_PSRM_R2, HCI_CLKOFF_INVALID, HCI_NO_ROLESWITCH);
246                 printf("HCI connect to %d returned %d\n",btm_fd,ret);
247                 ret = bt_HCI_recv_event(btm_fd, &hciev);
248                 while(1) {
249                         checkAndReload();
250                         ret = bt_HCI_recv_event(btm_fd, &hciev);
251                         if(hciev.event_code == HCI_EV_CONNECTION_COMPLETE) {
252                                 break;
253                         }
254                         VIDEO_WaitVSync();
255                 }
256                 if(hciev.data[0]) {
257                         printf("Connection failed!\n");
258                 } else {
259                         u16 chnd;
260                         chnd = hciev.data[1] | (hciev.data[2]<<8);
261                         printf("Connection successful! chnd: 0x%04x\n",chnd);
262                         ret = bt_L2CAP_send(btm_fd, chnd, 1, 8, (u8*)"\x02\x01\x04\x00\x13\x00\x41\x00");
263                         printf("L2CAP send to %d returned %d\n",btm_fd,ret);
264                         bt_HCI_recv_ACL_async(btm_fd, &acldat);
265                         bt_HCI_recv_ACL_async(btm_fd, &acldat);
266                         memcpy(&dcid, &acldat.data[8], 2);
267                         memcpy(l2pkt, "\x04\x01\x04\x00\xAA\xAA\x00\x00", 8);
268                         memcpy(&l2pkt[4], &dcid, 2);
269                         ret = bt_L2CAP_send(btm_fd, chnd, 1, 8, l2pkt);
270                         printf("L2CAP send to %d returned %d\n",btm_fd,ret);
271                         bt_HCI_recv_ACL_async(btm_fd, &acldat);
272                         bt_HCI_recv_ACL_async(btm_fd, &acldat);
273                         memcpy(l2pkt, "\x05\x01\x06\x00\xAA\xAA\x00\x00\x00\x00", 10);
274                         memcpy(&l2pkt[4], &dcid, 2);
275                         ret = bt_L2CAP_send(btm_fd, chnd, 1, 10, l2pkt);
276                         printf("L2CAP send to %d returned %d\n",btm_fd,ret);
277                         while(true) {
278                                 bt_HCI_recv_ACL_async(btm_fd, &acldat);
279                                 checkAndReload();
280                         }
281                 }
282         }
283         */
284         
285         /*ret = IOS_Close(btm_fd);
286         printf("IOS close USB: %d\n",ret);*/
287