bleh, tmp commit...
[ppcskel.git] / usb / drivers / bt.c
1 /*
2         ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
3         bluetooth driver
4
5 Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
6 Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
7
8 # This code is licensed to you under the terms of the GNU GPL, version 2;
9 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
10 */
11
12 #include "../core/core.h"
13 #include "../core/usb.h"
14 #include "../usbspec/usb11spec.h"
15 #include "../../malloc.h"
16 #include "../../string.h"
17
18 #include "bt.h"
19
20 #define USB_CREQ_D2H 0x80
21 #define USB_CREQ_STANDARD 0x00
22 #define USB_CREQ_VENDOR 0x40
23 #define USB_CREQ_INTERFACE 0x01
24 #define USB_CREQ_ENDPOINT 0x02
25 #define USB_CREQ_OTHER 0x03
26
27 #define SWAB16(x) ((((x)&0xFF)<<8)|((x)>>8))
28 #define EP_CONTROL 0x00
29 #define EP_EVENTS 0x81
30 #define EP_ACL_OUT 0x02
31 #define EP_ACL_IN 0x82
32
33 #define HCI_G_LINKCONTROL 1
34 #define HCI_G_LINKPOLICY 2
35 #define HCI_G_CONTROLLER 3
36 #define HCI_G_INFORMATIONAL 4
37 #define HCI_G_STATUS 5
38 #define HCI_G_TESTING 6
39
40 #define HCI_C_RESET 0x0003
41 #define HCI_LC_CONNECT 0x0005
42
43 #define HCI_PKTTYPE_DM1 0x0008
44 #define HCI_PSRM_R2 2
45 #define HCI_CLKOFF_INVALID 0
46 #define HCI_NO_ROLESWITCH 0
47
48 #define HCI_EV_CONNECTION_COMPLETE 0x03
49
50
51 typedef struct {
52         u8 event_code;
53         u8 data_length;
54         u8 *data;
55 } HCI_Event;
56
57 typedef struct {
58         u16 chnd;
59         int pb,bc;
60         u16 data_length;
61         u8 *data;
62 } HCI_ACL_Data;
63
64 int bt_HCI_reset(struct usb_device *dev);
65 int bt_HCI_recv_event(struct usb_device *dev, HCI_Event *ev);
66 int bt_HCI_connect(struct usb_device *dev, u8 *bdaddr, u16 pkt_types, u8 psrm, u16 clkoff, u8 roleswitch);
67 int bt_L2CAP_send(struct usb_device *dev, u16 chnd, u16 cid, u16 length, u8 *data);
68 int bt_HCI_recv_ACL_async(struct usb_device *dev, HCI_ACL_Data *acl);
69
70 struct usb_driver btd = {
71         .name     = "bt",
72         .probe  = usb_bt_probe,
73         .check  = usb_bt_check,
74         .remove = usb_bt_remove,
75         .data     = NULL
76 };
77
78 u8 epi_it, epi_bk, epo_bk;
79
80
81 void usb_bt_init()
82 {
83         usb_register_driver(&btd);
84
85         usb_set_configuration(btd.data, btd.data->conf->bConfigurationValue);
86         printf("get_conf: %d\n", usb_get_configuration(btd.data));
87
88         u8 buf[128];
89         memset(buf, 0, 8);
90         usb_control_msg(btd.data, 0x01, SET_INTERFACE, 0, 1, 0, buf, 0);
91
92         epi_it = btd.data->conf->intf->endp->bEndpointAddress & 0x7F;
93         epi_bk = btd.data->conf->intf->endp->next->bEndpointAddress & 0x7F;
94         epo_bk = btd.data->conf->intf->endp->next->next->bEndpointAddress & 0x7F;
95
96         btd.data->epSize[1] = btd.data->conf->intf->endp->wMaxPacketSize;
97         btd.data->epSize[2] = btd.data->conf->intf->endp->next->wMaxPacketSize;
98         btd.data->epSize[3] = btd.data->conf->intf->endp->next->next->wMaxPacketSize;
99         
100
101         /* shit */
102         // Bluetooth HCI reset command
103         u8 puf[8] ALIGNED(0x40);
104         memset(buf, 0, sizeof(buf));
105
106         memset(puf, 0, sizeof(puf));
107         memcpy(puf,"\x03\x0c\x00",3);
108         // Bluetooth request to control endpoint
109         u16 ret = usb_control_msg_pl(btd.data, 0x20, 0, 0, 0, 3, buf, 0, puf);
110         printf("request control endpoint:\n");
111         hexdump((void*) buf, 11);
112
113         ret = bt_HCI_reset(btd.data);
114         printf("HCI reset to *dev returned %d\n",ret);
115
116         HCI_Event hciev;
117         HCI_ACL_Data acldat;
118         ret = bt_HCI_recv_event(btd.data, &hciev);
119         printf("after recv event\n");
120
121         ret = bt_HCI_connect(btd.data, (u8*)"\x00\x17\xAB\x33\x37\x65", HCI_PKTTYPE_DM1, HCI_PSRM_R2, HCI_CLKOFF_INVALID, HCI_NO_ROLESWITCH);
122         printf("HCI connect to returned %d\n",ret);
123         ret = bt_HCI_recv_event(btd.data, &hciev);
124         while(1) {
125                 ret = bt_HCI_recv_event(btd.data, &hciev);
126                 if(hciev.event_code == HCI_EV_CONNECTION_COMPLETE) {
127                         break;
128                 }
129         }
130         if(hciev.data[0]) {
131                 printf("Connection failed!\n");
132         } else {
133                 u16 chnd;
134                 chnd = hciev.data[1] | (hciev.data[2]<<8);
135                 printf("Connection successful! chnd: 0x%04x\n",chnd);
136                 ret = bt_L2CAP_send(btd.data, chnd, 1, 8, (u8*)"\x02\x01\x04\x00\x13\x00\x41\x00");
137                 printf("L2CAP send to returned %d\n", ret);
138                 bt_HCI_recv_ACL_async(btd.data, &acldat);
139                 bt_HCI_recv_ACL_async(btd.data, &acldat);
140
141                 u8 dcid[256];
142                 u8 l2pkt[256];
143                 memset(dcid, 0, 256);
144                 memset(l2pkt, 0, 256);
145
146                 memcpy(&dcid, &acldat.data[8], 2);
147                 memcpy(l2pkt, "\x04\x01\x04\x00\xAA\xAA\x00\x00", 8);
148                 memcpy(&l2pkt[4], &dcid, 2);
149                 ret = bt_L2CAP_send(btd.data, chnd, 1, 8, l2pkt);
150                 printf("L2CAP send to returned %d\n", ret);
151                 bt_HCI_recv_ACL_async(btd.data, &acldat);
152                 bt_HCI_recv_ACL_async(btd.data, &acldat);
153                 memcpy(l2pkt, "\x05\x01\x06\x00\xAA\xAA\x00\x00\x00\x00", 10);
154                 memcpy(&l2pkt[4], &dcid, 2);
155                 ret = bt_L2CAP_send(btd.data, chnd, 1, 10, l2pkt);
156                 printf("L2CAP send to %d returned %d\n", btd.data, ret);
157                 while(1) {
158                         bt_HCI_recv_ACL_async(btd.data, &acldat);
159                 }
160         }
161 }
162
163 void usb_bt_probe()
164 {
165         struct usb_device *dev;
166         struct element *iterator = core.devices->head;
167
168         while(iterator != NULL) {
169                 dev = (struct usb_device*) iterator->data;
170                 if(dev == NULL) {
171                         continue;
172                 }
173
174                 if(dev->idVendor == 0x057e && dev->idProduct == 0x0305) {
175                         btd.data = dev;
176                 }
177
178                 iterator=iterator->next;
179         }
180 }
181
182 void usb_bt_check()
183 {
184 }
185
186 u8 usb_bt_inuse()
187 {
188         return btd.data ? 1 : 0;
189 }
190
191 void usb_bt_remove()
192 {
193         btd.data = NULL;
194 }
195
196 int bt_HCI_command(struct usb_device *dev, int ogf, int ocf, u8 *parameters, u8 parmlength)
197 {
198         int opcode;
199         static u8 buffer[0x103] ALIGNED(0x40);
200         opcode = (ocf&0x3FF) | ((ogf &0x3F)<<10);
201         buffer[0] = opcode&0xFF;
202         buffer[1] = opcode>>8;
203         buffer[2] = parmlength;
204         
205         if(parameters && parmlength) {
206                 memcpy (&buffer[3], parameters, parmlength);
207         } else {
208                 parmlength = 0; //make sure we don't pass around junk
209         }
210         printf("paramlength(should not >0xFF !): %x\n", parmlength+3);
211         
212         u8 buf[0x40];
213         memset(buf, 0, 0x40);
214         return usb_control_msg_pl(dev, 0x20, 0, 0, 0, parmlength+3, buf, 0, buffer);
215 }
216
217
218 int bt_HCI_recv_event(struct usb_device *dev, HCI_Event *ev)
219 {
220         static u8 buffer[0x102] ALIGNED(0x40);
221         s8 res;
222         
223         printf("WTF1\n");
224         res = usb_interrupt_read(dev, epi_it, buffer, sizeof(buffer), 0);
225         printf("WTF2\n");
226         ev->event_code = buffer[0];
227         ev->data_length = buffer[1];
228         ev->data = &buffer[2];
229         printf("HCI event [%d]: Code 0x%x, length %d, data:\n",res, ev->event_code, ev->data_length);
230         hexdump(ev->data, ev->data_length);
231         return res;
232 }
233
234 int bt_HCI_reset(struct usb_device *dev)
235 {
236         return bt_HCI_command(dev, HCI_G_CONTROLLER, HCI_C_RESET, NULL, 0);
237 }
238
239 int bt_HCI_connect(struct usb_device *dev, u8 *bdaddr, u16 pkt_types, u8 psrm, u16 clkoff, u8 roleswitch)
240 {
241         static u8 data[13];
242         int i;
243         for(i=0;i<6;i++)
244                 data[i] = bdaddr[5-i];
245         data[6] = pkt_types & 0xFF;
246         data[7] = pkt_types >> 8;
247         data[8] = psrm;
248         data[9] = 0; //reserved
249         data[10] = clkoff & 0xFF;
250         data[11] = clkoff >> 8;
251         data[12] = roleswitch;
252         
253         return bt_HCI_command(dev, HCI_G_LINKCONTROL, HCI_LC_CONNECT, data, sizeof(data));
254 }
255
256 int bt_HCI_send_ACL(struct usb_device *dev, u16 chnd, int pb, int bc, u16 length, u8 *data)
257 {
258         static u8 buffer[0x100] ALIGNED(0x40);
259         printf("<ACL chnd %04x pb %d bc %d len %d data:\n",chnd,pb,bc,length);
260         hexdump(data,length);
261         chnd &= 0x0FFF;
262         chnd |= pb<<12;
263         chnd |= bc<<14;
264         memcpy(&buffer[4],data,length);
265         buffer[0] = chnd & 0xFF;
266         buffer[1] = chnd >> 8;
267         buffer[2] = length & 0xFF;
268         buffer[3] = length >>8;
269         return usb_bulk_write(dev, EP_ACL_OUT, buffer, length+4, 0);
270 }
271
272 int bt_HCI_recv_ACL(struct usb_device *dev, HCI_ACL_Data *acl)
273 {
274         static u8 buffer[0x40] ALIGNED(0x40);
275         int res;
276         
277         res = usb_bulk_read(dev, EP_ACL_IN, buffer, sizeof(buffer), 0);
278         acl->chnd = buffer[0] | (buffer[1]<<8);
279         acl->pb = (acl->chnd & 0x3000)>>12;
280         acl->bc = (acl->chnd & 0xC000)>>14;
281         acl->chnd &= 0x0FFF;
282         acl->data_length = buffer[2] | (buffer[3]<<8);
283         acl->data = &buffer[4];
284         printf(">ACL [%d]: chnd %04x pb %d bc %d len %d data:\n",res,acl->chnd, acl->pb, acl->bc, acl->data_length);
285         hexdump(acl->data, acl->data_length);
286         return res;
287 }
288
289 int bt_HCI_recv_ACL_async(struct usb_device *dev, HCI_ACL_Data *acl)
290 {
291         static u8 buffer[0x40] ALIGNED(0x40);
292         int res;
293
294         res = usb_bulk_read(btd.data, EP_ACL_IN, buffer, sizeof(buffer), 0);
295
296         acl->chnd = buffer[0] | (buffer[1]<<8);
297         acl->pb = (acl->chnd & 0x3000)>>12;
298         acl->bc = (acl->chnd & 0xC000)>>14;
299         acl->chnd &= 0x0FFF;
300         acl->data_length = buffer[2] | (buffer[3]<<8);
301         acl->data = &buffer[4];
302         printf(">ACL [%d]: chnd %04x pb %d bc %d len %d data:\n",res,acl->chnd, acl->pb, acl->bc, acl->data_length);
303         hexdump(acl->data, acl->data_length);
304         return res;
305 }
306
307 int bt_L2CAP_send(struct usb_device *dev, u16 chnd, u16 cid, u16 length, u8 *data)
308 {
309         static u8 buffer[0x1000] ALIGNED(0x20);
310         memcpy(&buffer[4],data,length);
311         buffer[0] = length & 0xFF;
312         buffer[1] = length >> 8;
313         buffer[2] = cid & 0xFF;
314         buffer[3] = cid >> 8;
315         return bt_HCI_send_ACL(dev, chnd, 2, 0, length+4, buffer);
316 }
317