Add qemu 2.4.0
[kvmfornfv.git] / qemu / hw / bt / hci-csr.c
1 /*
2  * Bluetooth serial HCI transport.
3  * CSR41814 HCI with H4p vendor extensions.
4  *
5  * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 or
10  * (at your option) version 3 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "qemu-common.h"
22 #include "sysemu/char.h"
23 #include "qemu/timer.h"
24 #include "hw/irq.h"
25 #include "sysemu/bt.h"
26 #include "hw/bt.h"
27
28 struct csrhci_s {
29     int enable;
30     qemu_irq *pins;
31     int pin_state;
32     int modem_state;
33     CharDriverState chr;
34 #define FIFO_LEN        4096
35     int out_start;
36     int out_len;
37     int out_size;
38     uint8_t outfifo[FIFO_LEN * 2];
39     uint8_t inpkt[FIFO_LEN];
40     int in_len;
41     int in_hdr;
42     int in_data;
43     QEMUTimer *out_tm;
44     int64_t baud_delay;
45
46     bdaddr_t bd_addr;
47     struct HCIInfo *hci;
48 };
49
50 /* H4+ packet types */
51 enum {
52     H4_CMD_PKT   = 1,
53     H4_ACL_PKT   = 2,
54     H4_SCO_PKT   = 3,
55     H4_EVT_PKT   = 4,
56     H4_NEG_PKT   = 6,
57     H4_ALIVE_PKT = 7,
58 };
59
60 /* CSR41814 negotiation start magic packet */
61 static const uint8_t csrhci_neg_packet[] = {
62     H4_NEG_PKT, 10,
63     0x00, 0xa0, 0x01, 0x00, 0x00,
64     0x4c, 0x00, 0x96, 0x00, 0x00,
65 };
66
67 /* CSR41814 vendor-specific command OCFs */
68 enum {
69     OCF_CSR_SEND_FIRMWARE = 0x000,
70 };
71
72 static inline void csrhci_fifo_wake(struct csrhci_s *s)
73 {
74     if (!s->enable || !s->out_len)
75         return;
76
77     /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */
78     if (s->chr.chr_can_read && s->chr.chr_can_read(s->chr.handler_opaque) &&
79                     s->chr.chr_read) {
80         s->chr.chr_read(s->chr.handler_opaque,
81                         s->outfifo + s->out_start ++, 1);
82         s->out_len --;
83         if (s->out_start >= s->out_size) {
84             s->out_start = 0;
85             s->out_size = FIFO_LEN;
86         }
87     }
88
89     if (s->out_len)
90         timer_mod(s->out_tm, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->baud_delay);
91 }
92
93 #define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
94 static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
95 {
96     int off = s->out_start + s->out_len;
97
98     /* TODO: do the padding here, i.e. align len */
99     s->out_len += len;
100
101     if (off < FIFO_LEN) {
102         if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) {
103             fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
104             exit(-1);
105         }
106         return s->outfifo + off;
107     }
108
109     if (s->out_len > s->out_size) {
110         fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
111         exit(-1);
112     }
113
114     return s->outfifo + off - s->out_size;
115 }
116
117 static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
118                 int type, int len)
119 {
120     uint8_t *ret = csrhci_out_packetz(s, len + 2);
121
122     *ret ++ = type;
123     *ret ++ = len;
124
125     return ret;
126 }
127
128 static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
129                 int evt, int len)
130 {
131     uint8_t *ret = csrhci_out_packetz(s,
132                     len + 1 + sizeof(struct hci_event_hdr));
133
134     *ret ++ = H4_EVT_PKT;
135     ((struct hci_event_hdr *) ret)->evt = evt;
136     ((struct hci_event_hdr *) ret)->plen = len;
137
138     return ret + sizeof(struct hci_event_hdr);
139 }
140
141 static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf,
142                 uint8_t *data, int len)
143 {
144     int offset;
145     uint8_t *rpkt;
146
147     switch (ocf) {
148     case OCF_CSR_SEND_FIRMWARE:
149         /* Check if this is the bd_address packet */
150         if (len >= 18 + 8 && data[12] == 0x01 && data[13] == 0x00) {
151             offset = 18;
152             s->bd_addr.b[0] = data[offset + 7]; /* Beyond cmd packet end(!?) */
153             s->bd_addr.b[1] = data[offset + 6];
154             s->bd_addr.b[2] = data[offset + 4];
155             s->bd_addr.b[3] = data[offset + 0];
156             s->bd_addr.b[4] = data[offset + 3];
157             s->bd_addr.b[5] = data[offset + 2];
158
159             s->hci->bdaddr_set(s->hci, s->bd_addr.b);
160             fprintf(stderr, "%s: bd_address loaded from firmware: "
161                             "%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
162                             s->bd_addr.b[0], s->bd_addr.b[1], s->bd_addr.b[2],
163                             s->bd_addr.b[3], s->bd_addr.b[4], s->bd_addr.b[5]);
164         }
165
166         rpkt = csrhci_out_packet_event(s, EVT_VENDOR, 11);
167         /* Status bytes: no error */
168         rpkt[9] = 0x00;
169         rpkt[10] = 0x00;
170         break;
171
172     default:
173         fprintf(stderr, "%s: got a bad CMD packet\n", __FUNCTION__);
174         return;
175     }
176
177     csrhci_fifo_wake(s);
178 }
179
180 static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
181 {
182     uint8_t *rpkt;
183     int opc;
184
185     switch (*pkt ++) {
186     case H4_CMD_PKT:
187         opc = le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode);
188         if (cmd_opcode_ogf(opc) == OGF_VENDOR_CMD) {
189             csrhci_in_packet_vendor(s, cmd_opcode_ocf(opc),
190                             pkt + sizeof(struct hci_command_hdr),
191                             s->in_len - sizeof(struct hci_command_hdr) - 1);
192             return;
193         }
194
195         /* TODO: if the command is OCF_READ_LOCAL_COMMANDS or the likes,
196          * we need to send it to the HCI layer and then add our supported
197          * commands to the returned mask (such as OGF_VENDOR_CMD).  With
198          * bt-hci.c we could just have hooks for this kind of commands but
199          * we can't with bt-host.c.  */
200
201         s->hci->cmd_send(s->hci, pkt, s->in_len - 1);
202         break;
203
204     case H4_EVT_PKT:
205         goto bad_pkt;
206
207     case H4_ACL_PKT:
208         s->hci->acl_send(s->hci, pkt, s->in_len - 1);
209         break;
210
211     case H4_SCO_PKT:
212         s->hci->sco_send(s->hci, pkt, s->in_len - 1);
213         break;
214
215     case H4_NEG_PKT:
216         if (s->in_hdr != sizeof(csrhci_neg_packet) ||
217                         memcmp(pkt - 1, csrhci_neg_packet, s->in_hdr)) {
218             fprintf(stderr, "%s: got a bad NEG packet\n", __FUNCTION__);
219             return;
220         }
221         pkt += 2;
222
223         rpkt = csrhci_out_packet_csr(s, H4_NEG_PKT, 10);
224
225         *rpkt ++ = 0x20;        /* Operational settings negotiation Ok */
226         memcpy(rpkt, pkt, 7); rpkt += 7;
227         *rpkt ++ = 0xff;
228         *rpkt = 0xff;
229         break;
230
231     case H4_ALIVE_PKT:
232         if (s->in_hdr != 4 || pkt[1] != 0x55 || pkt[2] != 0x00) {
233             fprintf(stderr, "%s: got a bad ALIVE packet\n", __FUNCTION__);
234             return;
235         }
236
237         rpkt = csrhci_out_packet_csr(s, H4_ALIVE_PKT, 2);
238
239         *rpkt ++ = 0xcc;
240         *rpkt = 0x00;
241         break;
242
243     default:
244     bad_pkt:
245         /* TODO: error out */
246         fprintf(stderr, "%s: got a bad packet\n", __FUNCTION__);
247         break;
248     }
249
250     csrhci_fifo_wake(s);
251 }
252
253 static int csrhci_header_len(const uint8_t *pkt)
254 {
255     switch (pkt[0]) {
256     case H4_CMD_PKT:
257         return HCI_COMMAND_HDR_SIZE;
258     case H4_EVT_PKT:
259         return HCI_EVENT_HDR_SIZE;
260     case H4_ACL_PKT:
261         return HCI_ACL_HDR_SIZE;
262     case H4_SCO_PKT:
263         return HCI_SCO_HDR_SIZE;
264     case H4_NEG_PKT:
265         return pkt[1] + 1;
266     case H4_ALIVE_PKT:
267         return 3;
268     }
269
270     exit(-1);
271 }
272
273 static int csrhci_data_len(const uint8_t *pkt)
274 {
275     switch (*pkt ++) {
276     case H4_CMD_PKT:
277         /* It seems that vendor-specific command packets for H4+ are all
278          * one byte longer than indicated in the standard header.  */
279         if (le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode) == 0xfc00)
280             return (((struct hci_command_hdr *) pkt)->plen + 1) & ~1;
281
282         return ((struct hci_command_hdr *) pkt)->plen;
283     case H4_EVT_PKT:
284         return ((struct hci_event_hdr *) pkt)->plen;
285     case H4_ACL_PKT:
286         return le16_to_cpu(((struct hci_acl_hdr *) pkt)->dlen);
287     case H4_SCO_PKT:
288         return ((struct hci_sco_hdr *) pkt)->dlen;
289     case H4_NEG_PKT:
290     case H4_ALIVE_PKT:
291         return 0;
292     }
293
294     exit(-1);
295 }
296
297 static int csrhci_write(struct CharDriverState *chr,
298                 const uint8_t *buf, int len)
299 {
300     struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
301     int plen = s->in_len;
302
303     if (!s->enable)
304         return 0;
305
306     s->in_len += len;
307     memcpy(s->inpkt + plen, buf, len);
308
309     while (1) {
310         if (s->in_len >= 2 && plen < 2)
311             s->in_hdr = csrhci_header_len(s->inpkt) + 1;
312
313         if (s->in_len >= s->in_hdr && plen < s->in_hdr)
314             s->in_data = csrhci_data_len(s->inpkt) + s->in_hdr;
315
316         if (s->in_len >= s->in_data) {
317             csrhci_in_packet(s, s->inpkt);
318
319             memmove(s->inpkt, s->inpkt + s->in_len, s->in_len - s->in_data);
320             s->in_len -= s->in_data;
321             s->in_hdr = INT_MAX;
322             s->in_data = INT_MAX;
323             plen = 0;
324         } else
325             break;
326     }
327
328     return len;
329 }
330
331 static void csrhci_out_hci_packet_event(void *opaque,
332                 const uint8_t *data, int len)
333 {
334     struct csrhci_s *s = (struct csrhci_s *) opaque;
335     uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);        /* Align */
336
337     *pkt ++ = H4_EVT_PKT;
338     memcpy(pkt, data, len);
339
340     csrhci_fifo_wake(s);
341 }
342
343 static void csrhci_out_hci_packet_acl(void *opaque,
344                 const uint8_t *data, int len)
345 {
346     struct csrhci_s *s = (struct csrhci_s *) opaque;
347     uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);        /* Align */
348
349     *pkt ++ = H4_ACL_PKT;
350     pkt[len & ~1] = 0;
351     memcpy(pkt, data, len);
352
353     csrhci_fifo_wake(s);
354 }
355
356 static int csrhci_ioctl(struct CharDriverState *chr, int cmd, void *arg)
357 {
358     QEMUSerialSetParams *ssp;
359     struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
360     int prev_state = s->modem_state;
361
362     switch (cmd) {
363     case CHR_IOCTL_SERIAL_SET_PARAMS:
364         ssp = (QEMUSerialSetParams *) arg;
365         s->baud_delay = get_ticks_per_sec() / ssp->speed;
366         /* Moments later... (but shorter than 100ms) */
367         s->modem_state |= CHR_TIOCM_CTS;
368         break;
369
370     case CHR_IOCTL_SERIAL_GET_TIOCM:
371         *(int *) arg = s->modem_state;
372         break;
373
374     case CHR_IOCTL_SERIAL_SET_TIOCM:
375         s->modem_state = *(int *) arg;
376         if (~s->modem_state & prev_state & CHR_TIOCM_RTS)
377             s->modem_state &= ~CHR_TIOCM_CTS;
378         break;
379
380     default:
381         return -ENOTSUP;
382     }
383     return 0;
384 }
385
386 static void csrhci_reset(struct csrhci_s *s)
387 {
388     s->out_len = 0;
389     s->out_size = FIFO_LEN;
390     s->in_len = 0;
391     s->baud_delay = get_ticks_per_sec();
392     s->enable = 0;
393     s->in_hdr = INT_MAX;
394     s->in_data = INT_MAX;
395
396     s->modem_state = 0;
397     /* After a while... (but sooner than 10ms) */
398     s->modem_state |= CHR_TIOCM_CTS;
399
400     memset(&s->bd_addr, 0, sizeof(bdaddr_t));
401 }
402
403 static void csrhci_out_tick(void *opaque)
404 {
405     csrhci_fifo_wake((struct csrhci_s *) opaque);
406 }
407
408 static void csrhci_pins(void *opaque, int line, int level)
409 {
410     struct csrhci_s *s = (struct csrhci_s *) opaque;
411     int state = s->pin_state;
412
413     s->pin_state &= ~(1 << line);
414     s->pin_state |= (!!level) << line;
415
416     if ((state & ~s->pin_state) & (1 << csrhci_pin_reset)) {
417         /* TODO: Disappear from lower layers */
418         csrhci_reset(s);
419     }
420
421     if (s->pin_state == 3 && state != 3) {
422         s->enable = 1;
423         /* TODO: Wake lower layers up */
424     }
425 }
426
427 qemu_irq *csrhci_pins_get(CharDriverState *chr)
428 {
429     struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
430
431     return s->pins;
432 }
433
434 CharDriverState *uart_hci_init(qemu_irq wakeup)
435 {
436     struct csrhci_s *s = (struct csrhci_s *)
437             g_malloc0(sizeof(struct csrhci_s));
438
439     s->chr.opaque = s;
440     s->chr.chr_write = csrhci_write;
441     s->chr.chr_ioctl = csrhci_ioctl;
442     s->chr.avail_connections = 1;
443
444     s->hci = qemu_next_hci();
445     s->hci->opaque = s;
446     s->hci->evt_recv = csrhci_out_hci_packet_event;
447     s->hci->acl_recv = csrhci_out_hci_packet_acl;
448
449     s->out_tm = timer_new_ns(QEMU_CLOCK_VIRTUAL, csrhci_out_tick, s);
450     s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
451     csrhci_reset(s);
452
453     return &s->chr;
454 }