2 ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
5 Copyright (C) 2009 Bernhard Urban <lewurm@gmx.net>
6 Copyright (C) 2009 Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
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
12 #include "../core/core.h"
13 #include "../core/usb.h"
14 #include "../usbspec/usb11spec.h"
15 #include "../../malloc.h"
16 #include "../../string.h"
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
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
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
40 #define HCI_C_RESET 0x0003
41 #define HCI_LC_CONNECT 0x0005
43 #define HCI_PKTTYPE_DM1 0x0008
45 #define HCI_CLKOFF_INVALID 0
46 #define HCI_NO_ROLESWITCH 0
48 #define HCI_EV_CONNECTION_COMPLETE 0x03
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);
70 struct usb_driver btd = {
72 .probe = usb_bt_probe,
73 .check = usb_bt_check,
74 .remove = usb_bt_remove,
78 u8 epi_it, epi_bk, epo_bk;
83 usb_register_driver(&btd);
85 usb_set_configuration(btd.data, btd.data->conf->bConfigurationValue);
86 printf("get_conf: %d\n", usb_get_configuration(btd.data));
90 usb_control_msg(btd.data, 0x01, SET_INTERFACE, 0, 1, 0, buf, 0);
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;
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;
102 // Bluetooth HCI reset command
103 u8 puf[8] ALIGNED(0x40);
104 memset(buf, 0, sizeof(buf));
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);
113 ret = bt_HCI_reset(btd.data);
114 printf("HCI reset to *dev returned %d\n",ret);
118 ret = bt_HCI_recv_event(btd.data, &hciev);
119 printf("after recv event\n");
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);
125 ret = bt_HCI_recv_event(btd.data, &hciev);
126 if(hciev.event_code == HCI_EV_CONNECTION_COMPLETE) {
131 printf("Connection failed!\n");
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);
143 memset(dcid, 0, 256);
144 memset(l2pkt, 0, 256);
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);
158 bt_HCI_recv_ACL_async(btd.data, &acldat);
165 struct usb_device *dev;
166 struct element *iterator = core.devices->head;
168 while(iterator != NULL) {
169 dev = (struct usb_device*) iterator->data;
174 if(dev->idVendor == 0x057e && dev->idProduct == 0x0305) {
178 iterator=iterator->next;
188 return btd.data ? 1 : 0;
196 int bt_HCI_command(struct usb_device *dev, int ogf, int ocf, u8 *parameters, u8 parmlength)
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;
205 if(parameters && parmlength) {
206 memcpy (&buffer[3], parameters, parmlength);
208 parmlength = 0; //make sure we don't pass around junk
210 printf("paramlength(should not >0xFF !): %x\n", parmlength+3);
213 memset(buf, 0, 0x40);
214 return usb_control_msg_pl(dev, 0x20, 0, 0, 0, parmlength+3, buf, 0, buffer);
218 int bt_HCI_recv_event(struct usb_device *dev, HCI_Event *ev)
220 static u8 buffer[0x102] ALIGNED(0x40);
224 res = usb_interrupt_read(dev, epi_it, buffer, sizeof(buffer), 0);
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);
234 int bt_HCI_reset(struct usb_device *dev)
236 return bt_HCI_command(dev, HCI_G_CONTROLLER, HCI_C_RESET, NULL, 0);
239 int bt_HCI_connect(struct usb_device *dev, u8 *bdaddr, u16 pkt_types, u8 psrm, u16 clkoff, u8 roleswitch)
244 data[i] = bdaddr[5-i];
245 data[6] = pkt_types & 0xFF;
246 data[7] = pkt_types >> 8;
248 data[9] = 0; //reserved
249 data[10] = clkoff & 0xFF;
250 data[11] = clkoff >> 8;
251 data[12] = roleswitch;
253 return bt_HCI_command(dev, HCI_G_LINKCONTROL, HCI_LC_CONNECT, data, sizeof(data));
256 int bt_HCI_send_ACL(struct usb_device *dev, u16 chnd, int pb, int bc, u16 length, u8 *data)
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);
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);
272 int bt_HCI_recv_ACL(struct usb_device *dev, HCI_ACL_Data *acl)
274 static u8 buffer[0x40] ALIGNED(0x40);
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;
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);
289 int bt_HCI_recv_ACL_async(struct usb_device *dev, HCI_ACL_Data *acl)
291 static u8 buffer[0x40] ALIGNED(0x40);
294 res = usb_bulk_read(btd.data, EP_ACL_IN, buffer, sizeof(buffer), 0);
296 acl->chnd = buffer[0] | (buffer[1]<<8);
297 acl->pb = (acl->chnd & 0x3000)>>12;
298 acl->bc = (acl->chnd & 0xC000)>>14;
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);
307 int bt_L2CAP_send(struct usb_device *dev, u16 chnd, u16 cid, u16 length, u8 *data)
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);