1 /*
2 *
3 * Realtek Bluetooth USB driver
4 *
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/slab.h>
25 #include <linux/types.h>
26 #include <linux/sched.h>
27 #include <linux/errno.h>
28 #include <linux/skbuff.h>
29 #include <linux/dcache.h>
30 #include <linux/version.h>
31 #include <net/sock.h>
32 #include <net/bluetooth/bluetooth.h>
33 #include <net/bluetooth/hci_core.h>
34 #include <net/bluetooth/l2cap.h>
35
36 #include "rtk_coex.h"
37
38 /* Software coex message can be sent to and receive from WiFi driver by
39 * UDP socket or exported symbol */
40 /* #define RTK_COEX_OVER_SYMBOL */
41
42 #if BTRTL_HCI_IF == BTRTL_HCIUSB
43 #include <linux/usb.h>
44 #include "rtk_bt.h"
45 #undef RTKBT_DBG
46 #undef RTKBT_INFO
47 #undef RTKBT_WARN
48 #undef RTKBT_ERR
49
50 #elif BTRTL_HCI_IF == BTRTL_HCIUART
51 /* #define HCI_VERSION_CODE KERNEL_VERSION(3, 14, 41) */
52 #define HCI_VERSION_CODE LINUX_VERSION_CODE
53
54 #else
55 #error "Please set type of HCI interface"
56 #endif
57
58 #define RTK_VERSION "1.2"
59
60 #define RTKBT_DBG(fmt, arg...) printk(KERN_INFO "rtk_btcoex: " fmt "\n" , ## arg)
61 #define RTKBT_INFO(fmt, arg...) printk(KERN_INFO "rtk_btcoex: " fmt "\n" , ## arg)
62 #define RTKBT_WARN(fmt, arg...) printk(KERN_WARNING "rtk_btcoex: " fmt "\n", ## arg)
63 #define RTKBT_ERR(fmt, arg...) printk(KERN_WARNING "rtk_btcoex: " fmt "\n", ## arg)
64
65 static struct rtl_coex_struct btrtl_coex;
66
67 #ifdef RTB_SOFTWARE_MAILBOX
68 #ifdef RTK_COEX_OVER_SYMBOL
69 static struct sk_buff_head rtw_q;
70 static struct workqueue_struct *rtw_wq;
71 static struct work_struct rtw_work;
72 static u8 rtw_coex_on;
73 #endif
74 #endif
75
76 #define is_profile_connected(profile) ((btrtl_coex.profile_bitmap & BIT(profile)) > 0)
77 #define is_profile_busy(profile) ((btrtl_coex.profile_status & BIT(profile)) > 0)
78
79 #ifdef RTB_SOFTWARE_MAILBOX
80 static void rtk_handle_event_from_wifi(uint8_t * msg);
81 #endif
82
rtl_alloc_buff(struct rtl_coex_struct * coex)83 static int rtl_alloc_buff(struct rtl_coex_struct *coex)
84 {
85 struct rtl_hci_ev *ev;
86 struct rtl_l2_buff *l2;
87 int i;
88 int order;
89 unsigned long addr;
90 unsigned long addr2;
91 int ev_size;
92 int l2_size;
93 int n;
94
95 spin_lock_init(&coex->buff_lock);
96
97 INIT_LIST_HEAD(&coex->ev_used_list);
98 INIT_LIST_HEAD(&coex->ev_free_list);
99
100 INIT_LIST_HEAD(&coex->l2_used_list);
101 INIT_LIST_HEAD(&coex->l2_free_list);
102
103 n = NUM_RTL_HCI_EV * sizeof(struct rtl_hci_ev);
104 ev_size = ALIGN(n, sizeof(unsigned long));
105
106 n = L2_MAX_PKTS * sizeof(struct rtl_l2_buff);
107 l2_size = ALIGN(n, sizeof(unsigned long));
108
109 RTKBT_DBG("alloc buffers %d, %d for ev and l2", ev_size, l2_size);
110
111 order = get_order(ev_size + l2_size);
112 addr = __get_free_pages(GFP_KERNEL, order);
113 if (!addr) {
114 RTKBT_ERR("failed to alloc buffers for ev and l2.");
115 return -ENOMEM;
116 }
117 memset((void *)addr, 0, ev_size + l2_size);
118
119 coex->pages_addr = addr;
120 coex->buff_size = ev_size + l2_size;
121
122 ev = (struct rtl_hci_ev *)addr;
123 for (i = 0; i < NUM_RTL_HCI_EV; i++) {
124 list_add_tail(&ev->list, &coex->ev_free_list);
125 ev++;
126 }
127
128 addr2 = addr + ev_size;
129 l2 = (struct rtl_l2_buff *)addr2;
130 for (i = 0; i < L2_MAX_PKTS; i++) {
131 list_add_tail(&l2->list, &coex->l2_free_list);
132 l2++;
133 }
134
135 return 0;
136 }
137
rtl_free_buff(struct rtl_coex_struct * coex)138 static void rtl_free_buff(struct rtl_coex_struct *coex)
139 {
140 struct rtl_hci_ev *ev;
141 struct rtl_l2_buff *l2;
142 unsigned long flags;
143
144 spin_lock_irqsave(&coex->buff_lock, flags);
145
146 while (!list_empty(&coex->ev_used_list)) {
147 ev = list_entry(coex->ev_used_list.next, struct rtl_hci_ev,
148 list);
149 list_del(&ev->list);
150 }
151
152 while (!list_empty(&coex->ev_free_list)) {
153 ev = list_entry(coex->ev_free_list.next, struct rtl_hci_ev,
154 list);
155 list_del(&ev->list);
156 }
157
158 while (!list_empty(&coex->l2_used_list)) {
159 l2 = list_entry(coex->l2_used_list.next, struct rtl_l2_buff,
160 list);
161 list_del(&l2->list);
162 }
163
164 while (!list_empty(&coex->l2_free_list)) {
165 l2 = list_entry(coex->l2_free_list.next, struct rtl_l2_buff,
166 list);
167 list_del(&l2->list);
168 }
169
170 spin_unlock_irqrestore(&coex->buff_lock, flags);
171
172 if (coex->buff_size > 0) {
173 free_pages(coex->pages_addr, get_order(coex->buff_size));
174 coex->pages_addr = 0;
175 coex->buff_size = 0;
176 }
177 }
178
rtl_ev_node_get(struct rtl_coex_struct * coex)179 static struct rtl_hci_ev *rtl_ev_node_get(struct rtl_coex_struct *coex)
180 {
181 struct rtl_hci_ev *ev;
182 unsigned long flags;
183
184 if (!coex->buff_size)
185 return NULL;
186
187 spin_lock_irqsave(&coex->buff_lock, flags);
188 if (!list_empty(&coex->ev_free_list)) {
189 ev = list_entry(coex->ev_free_list.next, struct rtl_hci_ev,
190 list);
191 list_del(&ev->list);
192 } else
193 ev = NULL;
194 spin_unlock_irqrestore(&coex->buff_lock, flags);
195 return ev;
196 }
197
rtl_ev_node_to_used(struct rtl_coex_struct * coex,struct rtl_hci_ev * ev)198 static int rtl_ev_node_to_used(struct rtl_coex_struct *coex,
199 struct rtl_hci_ev *ev)
200 {
201 unsigned long flags;
202
203 spin_lock_irqsave(&coex->buff_lock, flags);
204 list_add_tail(&ev->list, &coex->ev_used_list);
205 spin_unlock_irqrestore(&coex->buff_lock, flags);
206
207 return 0;
208 }
209
rtl_l2_node_get(struct rtl_coex_struct * coex)210 static struct rtl_l2_buff *rtl_l2_node_get(struct rtl_coex_struct *coex)
211 {
212 struct rtl_l2_buff *l2;
213 unsigned long flags;
214
215 if (!coex->buff_size)
216 return NULL;
217
218 spin_lock_irqsave(&coex->buff_lock, flags);
219
220 if(!list_empty(&coex->l2_free_list)) {
221 l2 = list_entry(coex->l2_free_list.next, struct rtl_l2_buff,
222 list);
223 list_del(&l2->list);
224 } else
225 l2 = NULL;
226
227 spin_unlock_irqrestore(&coex->buff_lock, flags);
228 return l2;
229 }
230
rtl_l2_node_to_used(struct rtl_coex_struct * coex,struct rtl_l2_buff * l2)231 static int rtl_l2_node_to_used(struct rtl_coex_struct *coex,
232 struct rtl_l2_buff *l2)
233 {
234 unsigned long flags;
235
236 spin_lock_irqsave(&coex->buff_lock, flags);
237 list_add_tail(&l2->list, &coex->l2_used_list);
238 spin_unlock_irqrestore(&coex->buff_lock, flags);
239
240 return 0;
241 }
242
psm_to_profile_index(uint16_t psm)243 static int8_t psm_to_profile_index(uint16_t psm)
244 {
245 switch (psm) {
246 case PSM_AVCTP:
247 case PSM_SDP:
248 return -1; //ignore
249
250 case PSM_HID:
251 case PSM_HID_INT:
252 return profile_hid;
253
254 case PSM_AVDTP:
255 return profile_a2dp;
256
257 case PSM_PAN:
258 case PSM_OPP:
259 case PSM_FTP:
260 case PSM_BIP:
261 case PSM_RFCOMM:
262 return profile_pan;
263
264 default:
265 return profile_pan;
266 }
267 }
268
find_by_psm(u16 psm)269 static rtk_prof_info *find_by_psm(u16 psm)
270 {
271 struct list_head *head = &btrtl_coex.profile_list;
272 struct list_head *iter = NULL;
273 struct list_head *temp = NULL;
274 rtk_prof_info *desc = NULL;
275
276 list_for_each_safe(iter, temp, head) {
277 desc = list_entry(iter, rtk_prof_info, list);
278 if (desc->psm == psm)
279 return desc;
280 }
281
282 return NULL;
283 }
284
rtk_check_setup_timer(int8_t profile_index)285 static void rtk_check_setup_timer(int8_t profile_index)
286 {
287 if (profile_index == profile_a2dp) {
288 btrtl_coex.a2dp_packet_count = 0;
289 btrtl_coex.a2dp_count_timer.expires =
290 jiffies + msecs_to_jiffies(1000);
291 mod_timer(&btrtl_coex.a2dp_count_timer,
292 btrtl_coex.a2dp_count_timer.expires);
293 }
294
295 if (profile_index == profile_pan) {
296 btrtl_coex.pan_packet_count = 0;
297 btrtl_coex.pan_count_timer.expires =
298 jiffies + msecs_to_jiffies(1000);
299 mod_timer(&btrtl_coex.pan_count_timer,
300 btrtl_coex.pan_count_timer.expires);
301 }
302
303 /* hogp & voice share one timer now */
304 if ((profile_index == profile_hogp) || (profile_index == profile_voice)) {
305 if ((0 == btrtl_coex.profile_refcount[profile_hogp])
306 && (0 == btrtl_coex.profile_refcount[profile_voice])) {
307 btrtl_coex.hogp_packet_count = 0;
308 btrtl_coex.voice_packet_count = 0;
309 btrtl_coex.hogp_count_timer.expires =
310 jiffies + msecs_to_jiffies(1000);
311 mod_timer(&btrtl_coex.hogp_count_timer,
312 btrtl_coex.hogp_count_timer.expires);
313 }
314 }
315 }
316
rtk_check_del_timer(int8_t profile_index)317 static void rtk_check_del_timer(int8_t profile_index)
318 {
319 if (profile_a2dp == profile_index) {
320 btrtl_coex.a2dp_packet_count = 0;
321 del_timer_sync(&btrtl_coex.a2dp_count_timer);
322 }
323 if (profile_pan == profile_index) {
324 btrtl_coex.pan_packet_count = 0;
325 del_timer_sync(&btrtl_coex.pan_count_timer);
326 }
327 if (profile_hogp == profile_index) {
328 btrtl_coex.hogp_packet_count = 0;
329 if (btrtl_coex.profile_refcount[profile_voice] == 0) {
330 del_timer_sync(&btrtl_coex.hogp_count_timer);
331 }
332 }
333 if (profile_voice == profile_index) {
334 btrtl_coex.voice_packet_count = 0;
335 if (btrtl_coex.profile_refcount[profile_hogp] == 0) {
336 del_timer_sync(&btrtl_coex.hogp_count_timer);
337 }
338 }
339 }
340
341
342
find_connection_by_handle(struct rtl_coex_struct * coex,uint16_t handle)343 static rtk_conn_prof *find_connection_by_handle(struct rtl_coex_struct * coex,
344 uint16_t handle)
345 {
346 struct list_head *head = &coex->conn_hash;
347 struct list_head *iter = NULL, *temp = NULL;
348 rtk_conn_prof *desc = NULL;
349
350 list_for_each_safe(iter, temp, head) {
351 desc = list_entry(iter, rtk_conn_prof, list);
352 if ((handle & 0xEFF) == desc->handle) {
353 return desc;
354 }
355 }
356 return NULL;
357 }
358
allocate_connection_by_handle(uint16_t handle)359 static rtk_conn_prof *allocate_connection_by_handle(uint16_t handle)
360 {
361 rtk_conn_prof *phci_conn = NULL;
362 phci_conn = kmalloc(sizeof(rtk_conn_prof), GFP_ATOMIC);
363 if (phci_conn)
364 phci_conn->handle = handle;
365
366 return phci_conn;
367 }
368
init_connection_hash(struct rtl_coex_struct * coex)369 static void init_connection_hash(struct rtl_coex_struct * coex)
370 {
371 struct list_head *head = &coex->conn_hash;
372 INIT_LIST_HEAD(head);
373 }
374
add_connection_to_hash(struct rtl_coex_struct * coex,rtk_conn_prof * desc)375 static void add_connection_to_hash(struct rtl_coex_struct * coex,
376 rtk_conn_prof * desc)
377 {
378 struct list_head *head = &coex->conn_hash;
379 list_add_tail(&desc->list, head);
380 }
381
delete_connection_from_hash(rtk_conn_prof * desc)382 static void delete_connection_from_hash(rtk_conn_prof * desc)
383 {
384 if (desc) {
385 list_del(&desc->list);
386 kfree(desc);
387 }
388 }
389
flush_connection_hash(struct rtl_coex_struct * coex)390 static void flush_connection_hash(struct rtl_coex_struct * coex)
391 {
392 struct list_head *head = &coex->conn_hash;
393 struct list_head *iter = NULL, *temp = NULL;
394 rtk_conn_prof *desc = NULL;
395
396 list_for_each_safe(iter, temp, head) {
397 desc = list_entry(iter, rtk_conn_prof, list);
398 if (desc) {
399 list_del(&desc->list);
400 kfree(desc);
401 }
402 }
403 //INIT_LIST_HEAD(head);
404 }
405
init_profile_hash(struct rtl_coex_struct * coex)406 static void init_profile_hash(struct rtl_coex_struct * coex)
407 {
408 struct list_head *head = &coex->profile_list;
409 INIT_LIST_HEAD(head);
410 }
411
list_allocate_add(uint16_t handle,uint16_t psm,int8_t profile_index,uint16_t dcid,uint16_t scid)412 static uint8_t list_allocate_add(uint16_t handle, uint16_t psm,
413 int8_t profile_index, uint16_t dcid,
414 uint16_t scid)
415 {
416 rtk_prof_info *pprof_info = NULL;
417
418 if (profile_index < 0) {
419 RTKBT_ERR("PSM 0x%x do not need parse", psm);
420 return FALSE;
421 }
422
423 pprof_info = kmalloc(sizeof(rtk_prof_info), GFP_ATOMIC);
424
425 if (NULL == pprof_info) {
426 RTKBT_ERR("list_allocate_add: allocate error");
427 return FALSE;
428 }
429
430 /* Check if it is the second l2cap connection for a2dp
431 * a2dp signal channel will be created first than media channel.
432 */
433 if (psm == PSM_AVDTP) {
434 rtk_prof_info *pinfo = find_by_psm(psm);
435 if (!pinfo) {
436 pprof_info->flags = A2DP_SIGNAL;
437 RTKBT_INFO("%s: Add a2dp signal channel", __func__);
438 } else {
439 pprof_info->flags = A2DP_MEDIA;
440 RTKBT_INFO("%s: Add a2dp media channel", __func__);
441 }
442 }
443
444 pprof_info->handle = handle;
445 pprof_info->psm = psm;
446 pprof_info->scid = scid;
447 pprof_info->dcid = dcid;
448 pprof_info->profile_index = profile_index;
449 list_add_tail(&(pprof_info->list), &(btrtl_coex.profile_list));
450
451 return TRUE;
452 }
453
delete_profile_from_hash(rtk_prof_info * desc)454 static void delete_profile_from_hash(rtk_prof_info * desc)
455 {
456 RTKBT_DBG("Delete profile: hndl 0x%04x, psm 0x%04x, dcid 0x%04x, "
457 "scid 0x%04x", desc->handle, desc->psm, desc->dcid,
458 desc->scid);
459 if (desc) {
460 list_del(&desc->list);
461 kfree(desc);
462 desc = NULL;
463 }
464 }
465
flush_profile_hash(struct rtl_coex_struct * coex)466 static void flush_profile_hash(struct rtl_coex_struct * coex)
467 {
468 struct list_head *head = &coex->profile_list;
469 struct list_head *iter = NULL, *temp = NULL;
470 rtk_prof_info *desc = NULL;
471
472 spin_lock(&btrtl_coex.spin_lock_profile);
473 list_for_each_safe(iter, temp, head) {
474 desc = list_entry(iter, rtk_prof_info, list);
475 delete_profile_from_hash(desc);
476 }
477 //INIT_LIST_HEAD(head);
478 spin_unlock(&btrtl_coex.spin_lock_profile);
479 }
480
find_profile_by_handle_scid(struct rtl_coex_struct * coex,uint16_t handle,uint16_t scid)481 static rtk_prof_info *find_profile_by_handle_scid(struct rtl_coex_struct *
482 coex, uint16_t handle,
483 uint16_t scid)
484 {
485 struct list_head *head = &coex->profile_list;
486 struct list_head *iter = NULL, *temp = NULL;
487 rtk_prof_info *desc = NULL;
488
489 list_for_each_safe(iter, temp, head) {
490 desc = list_entry(iter, rtk_prof_info, list);
491 if (((handle & 0xFFF) == desc->handle) && (scid == desc->scid)) {
492 return desc;
493 }
494 }
495 return NULL;
496 }
497
find_profile_by_handle_dcid(struct rtl_coex_struct * coex,uint16_t handle,uint16_t dcid)498 static rtk_prof_info *find_profile_by_handle_dcid(struct rtl_coex_struct *
499 coex, uint16_t handle,
500 uint16_t dcid)
501 {
502 struct list_head *head = &coex->profile_list;
503 struct list_head *iter = NULL, *temp = NULL;
504 rtk_prof_info *desc = NULL;
505
506 list_for_each_safe(iter, temp, head) {
507 desc = list_entry(iter, rtk_prof_info, list);
508 if (((handle & 0xFFF) == desc->handle) && (dcid == desc->dcid)) {
509 return desc;
510 }
511 }
512 return NULL;
513 }
514
find_profile_by_handle_dcid_scid(struct rtl_coex_struct * coex,uint16_t handle,uint16_t dcid,uint16_t scid)515 static rtk_prof_info *find_profile_by_handle_dcid_scid(struct rtl_coex_struct
516 * coex, uint16_t handle,
517 uint16_t dcid,
518 uint16_t scid)
519 {
520 struct list_head *head = &coex->profile_list;
521 struct list_head *iter = NULL, *temp = NULL;
522 rtk_prof_info *desc = NULL;
523
524 list_for_each_safe(iter, temp, head) {
525 desc = list_entry(iter, rtk_prof_info, list);
526 if (((handle & 0xFFF) == desc->handle) && (dcid == desc->dcid)
527 && (scid == desc->scid)) {
528 return desc;
529 }
530 }
531 return NULL;
532 }
533
rtk_vendor_cmd_to_fw(uint16_t opcode,uint8_t parameter_len,uint8_t * parameter)534 static void rtk_vendor_cmd_to_fw(uint16_t opcode, uint8_t parameter_len,
535 uint8_t * parameter)
536 {
537 int len = HCI_CMD_PREAMBLE_SIZE + parameter_len;
538 uint8_t *p;
539 struct sk_buff *skb;
540 struct hci_dev *hdev = btrtl_coex.hdev;
541
542 if (!hdev) {
543 RTKBT_ERR("No HCI device");
544 return;
545 } else if (!test_bit(HCI_UP, &hdev->flags)) {
546 RTKBT_WARN("HCI device is down");
547 return;
548 }
549
550 skb = bt_skb_alloc(len, GFP_ATOMIC);
551 if (!skb) {
552 RTKBT_DBG("there is no room for cmd 0x%x", opcode);
553 return;
554 }
555
556 p = (uint8_t *) skb_put(skb, HCI_CMD_PREAMBLE_SIZE);
557 UINT16_TO_STREAM(p, opcode);
558 *p++ = parameter_len;
559
560 if (parameter_len)
561 memcpy(skb_put(skb, parameter_len), parameter, parameter_len);
562
563 bt_cb(skb)->pkt_type = HCI_COMMAND_PKT;
564
565 #if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
566 #if HCI_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
567 bt_cb(skb)->opcode = opcode;
568 #else
569 bt_cb(skb)->hci.opcode = opcode;
570 #endif
571 #endif
572
573 /* Stand-alone HCI commands must be flagged as
574 * single-command requests.
575 */
576 #if HCI_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)
577 #if HCI_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
578 bt_cb(skb)->req.start = true;
579 #else
580
581 #if HCI_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
582 bt_cb(skb)->hci.req_start = true;
583 #else
584
585 bt_cb(skb)->hci.req_flags |= HCI_REQ_START;
586 #endif
587
588 #endif /* 4.4.0 */
589 #endif /* 3.10.0 */
590 RTKBT_DBG("%s: opcode 0x%x", __func__, opcode);
591
592 /* It is harmless if set skb->dev twice. The dev will be used in
593 * btusb_send_frame() after or equal to kernel/hci 3.13.0,
594 * the hdev will not come from skb->dev. */
595 #if HCI_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
596 skb->dev = (void *)btrtl_coex.hdev;
597 #endif
598 /* Put the skb to the global hdev->cmd_q */
599 skb_queue_tail(&hdev->cmd_q, skb);
600
601 #if HCI_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
602 tasklet_schedule(&hdev->cmd_task);
603 #else
604 queue_work(hdev->workqueue, &hdev->cmd_work);
605 #endif
606
607 return;
608 }
609
rtk_notify_profileinfo_to_fw(void)610 static void rtk_notify_profileinfo_to_fw(void)
611 {
612 struct list_head *head = NULL;
613 struct list_head *iter = NULL;
614 struct list_head *temp = NULL;
615 rtk_conn_prof *hci_conn = NULL;
616 uint8_t handle_number = 0;
617 uint32_t buffer_size = 0;
618 uint8_t *p_buf = NULL;
619 uint8_t *p = NULL;
620
621 head = &btrtl_coex.conn_hash;
622 list_for_each_safe(iter, temp, head) {
623 hci_conn = list_entry(iter, rtk_conn_prof, list);
624 if (hci_conn && hci_conn->profile_bitmap)
625 handle_number++;
626 }
627
628 buffer_size = 1 + handle_number * 3 + 1;
629
630 p_buf = kmalloc(buffer_size, GFP_ATOMIC);
631
632 if (NULL == p_buf) {
633 RTKBT_ERR("%s: alloc error", __func__);
634 return;
635 }
636 p = p_buf;
637
638 RTKBT_DBG("%s: BufferSize %u", __func__, buffer_size);
639 *p++ = handle_number;
640 RTKBT_DBG("%s: NumberOfHandles %u", __func__, handle_number);
641 head = &btrtl_coex.conn_hash;
642 list_for_each(iter, head) {
643 hci_conn = list_entry(iter, rtk_conn_prof, list);
644 if (hci_conn && hci_conn->profile_bitmap) {
645 UINT16_TO_STREAM(p, hci_conn->handle);
646 RTKBT_DBG("%s: handle 0x%04x", __func__,
647 hci_conn->handle);
648 *p++ = hci_conn->profile_bitmap;
649 RTKBT_DBG("%s: profile_bitmap 0x%02x", __func__,
650 hci_conn->profile_bitmap);
651 handle_number--;
652 }
653 if (0 == handle_number)
654 break;
655 }
656
657 *p++ = btrtl_coex.profile_status;
658 RTKBT_DBG("%s: profile_status 0x%02x", __func__,
659 btrtl_coex.profile_status);
660
661 rtk_vendor_cmd_to_fw(HCI_VENDOR_SET_PROFILE_REPORT_COMMAND, buffer_size,
662 p_buf);
663
664 kfree(p_buf);
665 return;
666 }
667
update_profile_state(uint8_t profile_index,uint8_t is_busy)668 static void update_profile_state(uint8_t profile_index, uint8_t is_busy)
669 {
670 uint8_t need_update = FALSE;
671
672 if ((btrtl_coex.profile_bitmap & BIT(profile_index)) == 0) {
673 RTKBT_ERR("%s: : ERROR!!! profile(Index: %x) does not exist",
674 __func__, profile_index);
675 return;
676 }
677
678 if (is_busy) {
679 if ((btrtl_coex.profile_status & BIT(profile_index)) == 0) {
680 need_update = TRUE;
681 btrtl_coex.profile_status |= BIT(profile_index);
682 }
683 } else {
684 if ((btrtl_coex.profile_status & BIT(profile_index)) > 0) {
685 need_update = TRUE;
686 btrtl_coex.profile_status &= ~(BIT(profile_index));
687 }
688 }
689
690 if (need_update) {
691 RTKBT_DBG("%s: btrtl_coex.profie_bitmap = %x",
692 __func__, btrtl_coex.profile_bitmap);
693 RTKBT_DBG("%s: btrtl_coex.profile_status = %x",
694 __func__, btrtl_coex.profile_status);
695 rtk_notify_profileinfo_to_fw();
696 }
697 }
698
update_profile_connection(rtk_conn_prof * phci_conn,int8_t profile_index,uint8_t is_add)699 static void update_profile_connection(rtk_conn_prof * phci_conn,
700 int8_t profile_index, uint8_t is_add)
701 {
702 uint8_t need_update = FALSE;
703 uint8_t kk;
704
705 RTKBT_DBG("%s: is_add %d, profile_index %x", __func__,
706 is_add, profile_index);
707 if (profile_index < 0)
708 return;
709
710 if (is_add) {
711 if (btrtl_coex.profile_refcount[profile_index] == 0) {
712 need_update = TRUE;
713 btrtl_coex.profile_bitmap |= BIT(profile_index);
714
715 /* SCO is always busy */
716 if (profile_index == profile_sco)
717 btrtl_coex.profile_status |=
718 BIT(profile_index);
719
720 rtk_check_setup_timer(profile_index);
721 }
722 btrtl_coex.profile_refcount[profile_index]++;
723
724 if (0 == phci_conn->profile_refcount[profile_index]) {
725 need_update = TRUE;
726 phci_conn->profile_bitmap |= BIT(profile_index);
727 }
728 phci_conn->profile_refcount[profile_index]++;
729 } else {
730 if (!btrtl_coex.profile_refcount[profile_index]) {
731 RTKBT_WARN("profile %u refcount is already zero",
732 profile_index);
733 return;
734 }
735 btrtl_coex.profile_refcount[profile_index]--;
736 RTKBT_DBG("%s: btrtl_coex.profile_refcount[%x] = %x",
737 __func__, profile_index,
738 btrtl_coex.profile_refcount[profile_index]);
739 if (btrtl_coex.profile_refcount[profile_index] == 0) {
740 need_update = TRUE;
741 btrtl_coex.profile_bitmap &= ~(BIT(profile_index));
742
743 /* if profile does not exist, status is meaningless */
744 btrtl_coex.profile_status &= ~(BIT(profile_index));
745 rtk_check_del_timer(profile_index);
746 }
747
748 phci_conn->profile_refcount[profile_index]--;
749 if (0 == phci_conn->profile_refcount[profile_index]) {
750 need_update = TRUE;
751 phci_conn->profile_bitmap &= ~(BIT(profile_index));
752
753 /* clear profile_hid_interval if need */
754 if ((profile_hid == profile_index)
755 && (phci_conn->
756 profile_bitmap & (BIT(profile_hid_interval)))) {
757 phci_conn->profile_bitmap &=
758 ~(BIT(profile_hid_interval));
759 btrtl_coex.
760 profile_refcount[profile_hid_interval]--;
761 }
762 }
763 }
764
765 RTKBT_DBG("%s: btrtl_coex.profile_bitmap 0x%02x", __func__,
766 btrtl_coex.profile_bitmap);
767 for (kk = 0; kk < 8; kk++)
768 RTKBT_DBG("%s: btrtl_coex.profile_refcount[%d] = %d",
769 __func__, kk,
770 btrtl_coex.profile_refcount[kk]);
771
772 if (need_update)
773 rtk_notify_profileinfo_to_fw();
774 }
775
update_hid_active_state(uint16_t handle,uint16_t interval)776 static void update_hid_active_state(uint16_t handle, uint16_t interval)
777 {
778 uint8_t need_update = 0;
779 rtk_conn_prof *phci_conn =
780 find_connection_by_handle(&btrtl_coex, handle);
781
782 if (phci_conn == NULL)
783 return;
784
785 RTKBT_DBG("%s: handle 0x%04x, interval %u", __func__, handle, interval);
786 if (((phci_conn->profile_bitmap) & (BIT(profile_hid))) == 0) {
787 RTKBT_DBG("HID not connected, nothing to be down");
788 return;
789 }
790
791 if (interval < 60) {
792 if ((phci_conn->profile_bitmap & (BIT(profile_hid_interval))) ==
793 0) {
794 need_update = 1;
795 phci_conn->profile_bitmap |= BIT(profile_hid_interval);
796
797 btrtl_coex.profile_refcount[profile_hid_interval]++;
798 if (btrtl_coex.
799 profile_refcount[profile_hid_interval] == 1)
800 btrtl_coex.profile_status |=
801 BIT(profile_hid);
802 }
803 } else {
804 if ((phci_conn->profile_bitmap & (BIT(profile_hid_interval)))) {
805 need_update = 1;
806 phci_conn->profile_bitmap &=
807 ~(BIT(profile_hid_interval));
808
809 btrtl_coex.profile_refcount[profile_hid_interval]--;
810 if (btrtl_coex.
811 profile_refcount[profile_hid_interval] == 0)
812 btrtl_coex.profile_status &=
813 ~(BIT(profile_hid));
814 }
815 }
816
817 if (need_update)
818 rtk_notify_profileinfo_to_fw();
819 }
820
handle_l2cap_con_req(uint16_t handle,uint16_t psm,uint16_t scid,uint8_t direction)821 static uint8_t handle_l2cap_con_req(uint16_t handle, uint16_t psm,
822 uint16_t scid, uint8_t direction)
823 {
824 uint8_t status = FALSE;
825 rtk_prof_info *prof_info = NULL;
826 int8_t profile_index = psm_to_profile_index(psm);
827
828 if (profile_index < 0) {
829 RTKBT_DBG("PSM(0x%04x) do not need parse", psm);
830 return status;
831 }
832
833 spin_lock(&btrtl_coex.spin_lock_profile);
834 if (direction) //1: out
835 prof_info =
836 find_profile_by_handle_scid(&btrtl_coex, handle, scid);
837 else // 0:in
838 prof_info =
839 find_profile_by_handle_dcid(&btrtl_coex, handle, scid);
840
841 if (prof_info) {
842 RTKBT_DBG("%s: this profile is already exist!", __func__);
843 spin_unlock(&btrtl_coex.spin_lock_profile);
844 return status;
845 }
846
847 if (direction) //1: out
848 status = list_allocate_add(handle, psm, profile_index, 0, scid);
849 else // 0:in
850 status = list_allocate_add(handle, psm, profile_index, scid, 0);
851
852 spin_unlock(&btrtl_coex.spin_lock_profile);
853
854 if (!status)
855 RTKBT_ERR("%s: list_allocate_add failed!", __func__);
856
857 return status;
858 }
859
handle_l2cap_con_rsp(uint16_t handle,uint16_t dcid,uint16_t scid,uint8_t direction,uint8_t result)860 static uint8_t handle_l2cap_con_rsp(uint16_t handle, uint16_t dcid,
861 uint16_t scid, uint8_t direction,
862 uint8_t result)
863 {
864 rtk_prof_info *prof_info = NULL;
865 rtk_conn_prof *phci_conn = NULL;
866
867 spin_lock(&btrtl_coex.spin_lock_profile);
868 if (!direction) //0, in
869 prof_info =
870 find_profile_by_handle_scid(&btrtl_coex, handle, scid);
871 else //1, out
872 prof_info =
873 find_profile_by_handle_dcid(&btrtl_coex, handle, scid);
874
875 if (!prof_info) {
876 //RTKBT_DBG("handle_l2cap_con_rsp: prof_info Not Find!!");
877 spin_unlock(&btrtl_coex.spin_lock_profile);
878 return FALSE;
879 }
880
881 if (!result) { //success
882 RTKBT_DBG("l2cap connection success, update connection");
883 if (!direction) //0, in
884 prof_info->dcid = dcid;
885 else //1, out
886 prof_info->scid = dcid;
887
888 phci_conn = find_connection_by_handle(&btrtl_coex, handle);
889 if (phci_conn)
890 update_profile_connection(phci_conn,
891 prof_info->profile_index,
892 TRUE);
893 }
894
895 spin_unlock(&btrtl_coex.spin_lock_profile);
896 return TRUE;
897 }
898
handle_l2cap_discon_req(uint16_t handle,uint16_t dcid,uint16_t scid,uint8_t direction)899 static uint8_t handle_l2cap_discon_req(uint16_t handle, uint16_t dcid,
900 uint16_t scid, uint8_t direction)
901 {
902 rtk_prof_info *prof_info = NULL;
903 rtk_conn_prof *phci_conn = NULL;
904 RTKBT_DBG("%s: handle 0x%04x, dcid 0x%04x, scid 0x%04x, dir %u",
905 __func__, handle, dcid, scid, direction);
906
907 spin_lock(&btrtl_coex.spin_lock_profile);
908 if (!direction) //0: in
909 prof_info =
910 find_profile_by_handle_dcid_scid(&btrtl_coex, handle,
911 scid, dcid);
912 else //1: out
913 prof_info =
914 find_profile_by_handle_dcid_scid(&btrtl_coex, handle,
915 dcid, scid);
916
917 if (!prof_info) {
918 //LogMsg("handle_l2cap_discon_req: prof_info Not Find!");
919 spin_unlock(&btrtl_coex.spin_lock_profile);
920 return 0;
921 }
922
923 phci_conn = find_connection_by_handle(&btrtl_coex, handle);
924 if (!phci_conn) {
925 spin_unlock(&btrtl_coex.spin_lock_profile);
926 return 0;
927 }
928
929 update_profile_connection(phci_conn, prof_info->profile_index, FALSE);
930 if (prof_info->profile_index == profile_a2dp &&
931 (phci_conn->profile_bitmap & BIT(profile_sink)))
932 update_profile_connection(phci_conn, profile_sink, FALSE);
933
934 delete_profile_from_hash(prof_info);
935 spin_unlock(&btrtl_coex.spin_lock_profile);
936
937 return 1;
938 }
939
940 static const char sample_freqs[4][8] = {
941 "16", "32", "44.1", "48"
942 };
943
944 static const uint8_t sbc_blocks[4] = { 4, 8, 12, 16 };
945
946 static const char chan_modes[4][16] = {
947 "MONO", "DUAL_CHANNEL", "STEREO", "JOINT_STEREO"
948 };
949
950 static const char alloc_methods[2][12] = {
951 "LOUDNESS", "SNR"
952 };
953
954 static const uint8_t subbands[2] = { 4, 8 };
955
print_sbc_header(struct sbc_frame_hdr * hdr)956 void print_sbc_header(struct sbc_frame_hdr *hdr)
957 {
958 RTKBT_DBG("syncword: %02x", hdr->syncword);
959 RTKBT_DBG("freq %skHz", sample_freqs[hdr->sampling_frequency]);
960 RTKBT_DBG("blocks %u", sbc_blocks[hdr->blocks]);
961 RTKBT_DBG("channel mode %s", chan_modes[hdr->channel_mode]);
962 RTKBT_DBG("allocation method %s",
963 alloc_methods[hdr->allocation_method]);
964 RTKBT_DBG("subbands %u", subbands[hdr->subbands]);
965 }
966
packets_count(uint16_t handle,uint16_t scid,uint16_t length,uint8_t direction,u8 * user_data)967 static void packets_count(uint16_t handle, uint16_t scid, uint16_t length,
968 uint8_t direction, u8 *user_data)
969 {
970 rtk_prof_info *prof_info = NULL;
971
972 rtk_conn_prof *hci_conn =
973 find_connection_by_handle(&btrtl_coex, handle);
974 if (NULL == hci_conn)
975 return;
976
977 if (0 == hci_conn->type) {
978 if (!direction) //0: in
979 prof_info =
980 find_profile_by_handle_scid(&btrtl_coex, handle,
981 scid);
982 else //1: out
983 prof_info =
984 find_profile_by_handle_dcid(&btrtl_coex, handle,
985 scid);
986
987 if (!prof_info) {
988 //RTKBT_DBG("packets_count: prof_info Not Find!");
989 return;
990 }
991
992 /* avdtp media data */
993 if (prof_info->profile_index == profile_a2dp &&
994 prof_info->flags == A2DP_MEDIA) {
995 if (!is_profile_busy(profile_a2dp)) {
996 struct sbc_frame_hdr *sbc_header;
997 struct rtp_header *rtph;
998 u8 bitpool;
999
1000 update_profile_state(profile_a2dp, TRUE);
1001 if (!direction) {
1002 if (!(hci_conn->profile_bitmap & BIT(profile_sink))) {
1003 btrtl_coex.profile_bitmap |= BIT(profile_sink);
1004 hci_conn->profile_bitmap |= BIT(profile_sink);
1005 update_profile_connection(hci_conn, profile_sink, 1);
1006 }
1007 update_profile_state(profile_sink, TRUE);
1008 }
1009
1010 /* We assume it is SBC if the packet length
1011 * is bigger than 100 bytes
1012 */
1013 if (length > 100) {
1014 RTKBT_INFO("Length %u", length);
1015 rtph = (struct rtp_header *)user_data;
1016
1017 RTKBT_DBG("rtp: v %u, cc %u, pt %u",
1018 rtph->v, rtph->cc, rtph->pt);
1019 /* move forward */
1020 user_data += sizeof(struct rtp_header) +
1021 rtph->cc * 4 + 1;
1022
1023 /* point to the sbc frame header */
1024 sbc_header = (struct sbc_frame_hdr *)user_data;
1025 bitpool = sbc_header->bitpool;
1026
1027 print_sbc_header(sbc_header);
1028
1029 RTKBT_DBG("bitpool %u", bitpool);
1030
1031 rtk_vendor_cmd_to_fw(HCI_VENDOR_SET_BITPOOL,
1032 1, &bitpool);
1033 }
1034 }
1035 btrtl_coex.a2dp_packet_count++;
1036 }
1037
1038 if (prof_info->profile_index == profile_pan)
1039 btrtl_coex.pan_packet_count++;
1040 }
1041 }
1042
1043 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
count_a2dp_packet_timeout(struct timer_list * unused)1044 static void count_a2dp_packet_timeout(struct timer_list *unused)
1045 #else
1046 static void count_a2dp_packet_timeout(unsigned long data)
1047 #endif
1048 {
1049 if (btrtl_coex.a2dp_packet_count)
1050 RTKBT_DBG("%s: a2dp_packet_count %d", __func__,
1051 btrtl_coex.a2dp_packet_count);
1052 if (btrtl_coex.a2dp_packet_count == 0) {
1053 if (is_profile_busy(profile_a2dp)) {
1054 RTKBT_DBG("%s: a2dp busy->idle!", __func__);
1055 update_profile_state(profile_a2dp, FALSE);
1056 if (btrtl_coex.profile_bitmap & BIT(profile_sink))
1057 update_profile_state(profile_sink, FALSE);
1058 }
1059 }
1060 btrtl_coex.a2dp_packet_count = 0;
1061 mod_timer(&btrtl_coex.a2dp_count_timer,
1062 jiffies + msecs_to_jiffies(1000));
1063 }
1064
1065 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
count_pan_packet_timeout(struct timer_list * unused)1066 static void count_pan_packet_timeout(struct timer_list *unused)
1067 #else
1068 static void count_pan_packet_timeout(unsigned long data)
1069 #endif
1070 {
1071 if (btrtl_coex.pan_packet_count)
1072 RTKBT_DBG("%s: pan_packet_count %d", __func__,
1073 btrtl_coex.pan_packet_count);
1074 if (btrtl_coex.pan_packet_count < PAN_PACKET_COUNT) {
1075 if (is_profile_busy(profile_pan)) {
1076 RTKBT_DBG("%s: pan busy->idle!", __func__);
1077 update_profile_state(profile_pan, FALSE);
1078 }
1079 } else {
1080 if (!is_profile_busy(profile_pan)) {
1081 RTKBT_DBG("timeout_handler: pan idle->busy!");
1082 update_profile_state(profile_pan, TRUE);
1083 }
1084 }
1085 btrtl_coex.pan_packet_count = 0;
1086 mod_timer(&btrtl_coex.pan_count_timer,
1087 jiffies + msecs_to_jiffies(1000));
1088 }
1089
1090 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
count_hogp_packet_timeout(struct timer_list * unused)1091 static void count_hogp_packet_timeout(struct timer_list *unused)
1092 #else
1093 static void count_hogp_packet_timeout(unsigned long data)
1094 #endif
1095 {
1096 if (btrtl_coex.hogp_packet_count)
1097 RTKBT_DBG("%s: hogp_packet_count %d", __func__,
1098 btrtl_coex.hogp_packet_count);
1099 if (btrtl_coex.hogp_packet_count == 0) {
1100 if (is_profile_busy(profile_hogp)) {
1101 RTKBT_DBG("%s: hogp busy->idle!", __func__);
1102 update_profile_state(profile_hogp, FALSE);
1103 }
1104 }
1105 btrtl_coex.hogp_packet_count = 0;
1106
1107 if (btrtl_coex.voice_packet_count)
1108 RTKBT_DBG("%s: voice_packet_count %d", __func__,
1109 btrtl_coex.voice_packet_count);
1110 if (btrtl_coex.voice_packet_count == 0) {
1111 if (is_profile_busy(profile_voice)) {
1112 RTKBT_DBG("%s: voice busy->idle!", __func__);
1113 update_profile_state(profile_voice, FALSE);
1114 }
1115 }
1116 btrtl_coex.voice_packet_count = 0;
1117 mod_timer(&btrtl_coex.hogp_count_timer,
1118 jiffies + msecs_to_jiffies(1000));
1119 }
1120
1121 #ifdef RTB_SOFTWARE_MAILBOX
1122
1123 #ifndef RTK_COEX_OVER_SYMBOL
udpsocket_send(char * tx_msg,int msg_size)1124 static int udpsocket_send(char *tx_msg, int msg_size)
1125 {
1126 u8 error = 0;
1127 struct msghdr udpmsg;
1128 mm_segment_t oldfs;
1129 struct iovec iov;
1130
1131 RTKBT_DBG("send msg %s with len:%d", tx_msg, msg_size);
1132
1133 if (btrtl_coex.sock_open) {
1134 iov.iov_base = (void *)tx_msg;
1135 iov.iov_len = msg_size;
1136 udpmsg.msg_name = &btrtl_coex.wifi_addr;
1137 udpmsg.msg_namelen = sizeof(struct sockaddr_in);
1138 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)
1139 udpmsg.msg_iov = &iov;
1140 udpmsg.msg_iovlen = 1;
1141 #else
1142 iov_iter_init(&udpmsg.msg_iter, WRITE, &iov, 1, msg_size);
1143 #endif
1144 udpmsg.msg_control = NULL;
1145 udpmsg.msg_controllen = 0;
1146 udpmsg.msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL;
1147 oldfs = get_fs();
1148 set_fs(KERNEL_DS);
1149 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
1150 error = sock_sendmsg(btrtl_coex.udpsock, &udpmsg, msg_size);
1151 #else
1152 error = sock_sendmsg(btrtl_coex.udpsock, &udpmsg);
1153 #endif
1154 set_fs(oldfs);
1155
1156 if (error < 0)
1157 RTKBT_DBG("Error when sendimg msg, error:%d", error);
1158 }
1159
1160 return error;
1161 }
1162 #endif
1163
1164 #ifdef RTK_COEX_OVER_SYMBOL
1165 /* Receive message from WiFi */
rtw_btcoex_wifi_to_bt(u8 * msg,u8 msg_size)1166 u8 rtw_btcoex_wifi_to_bt(u8 *msg, u8 msg_size)
1167 {
1168 struct sk_buff *nskb;
1169
1170 if (!rtw_coex_on) {
1171 RTKBT_WARN("Bluetooth is closed");
1172 return 0;
1173 }
1174
1175 nskb = alloc_skb(msg_size, GFP_ATOMIC);
1176 if (!nskb) {
1177 RTKBT_ERR("Couldnt alloc skb for WiFi coex message");
1178 return 0;
1179 }
1180
1181 memcpy(skb_put(nskb, msg_size), msg, msg_size);
1182 skb_queue_tail(&rtw_q, nskb);
1183
1184 queue_work(rtw_wq, &rtw_work);
1185
1186 return 1;
1187 }
1188 EXPORT_SYMBOL(rtw_btcoex_wifi_to_bt);
1189
rtk_send_coexmsg2wifi(u8 * msg,u8 size)1190 static int rtk_send_coexmsg2wifi(u8 *msg, u8 size)
1191 {
1192 u8 result;
1193 u8 (*btmsg_to_wifi)(u8 *, u8);
1194
1195 btmsg_to_wifi = __symbol_get(VMLINUX_SYMBOL_STR(rtw_btcoex_bt_to_wifi));
1196
1197 if (!btmsg_to_wifi) {
1198 /* RTKBT_ERR("Couldnt get symbol"); */
1199 return -1;
1200 }
1201
1202 result = btmsg_to_wifi(msg, size);
1203 __symbol_put(VMLINUX_SYMBOL_STR(rtw_btcoex_bt_to_wifi));
1204 if (!result) {
1205 RTKBT_ERR("Couldnt send coex msg to WiFi");
1206 return -1;
1207 } else if (result == 1){
1208 /* successful to send message */
1209 return 0;
1210 } else {
1211 RTKBT_ERR("Unknown result %d", result);
1212 return -1;
1213 }
1214 }
1215
rtkbt_process_coexskb(struct sk_buff * skb)1216 static int rtkbt_process_coexskb(struct sk_buff *skb)
1217 {
1218 rtk_handle_event_from_wifi(skb->data);
1219 return 0;
1220 }
1221
rtw_work_func(struct work_struct * work)1222 static void rtw_work_func(struct work_struct *work)
1223 {
1224 struct sk_buff *skb;
1225
1226 while ((skb = skb_dequeue(&rtw_q))) {
1227 rtkbt_process_coexskb(skb);
1228 kfree_skb(skb);
1229 }
1230 }
1231
1232 #endif
1233
rtkbt_coexmsg_send(char * tx_msg,int msg_size)1234 static int rtkbt_coexmsg_send(char *tx_msg, int msg_size)
1235 {
1236 #ifdef RTK_COEX_OVER_SYMBOL
1237 return rtk_send_coexmsg2wifi((uint8_t *)tx_msg, (u8)msg_size);
1238 #else
1239 return udpsocket_send(tx_msg, msg_size);
1240 #endif
1241 }
1242
1243 #ifndef RTK_COEX_OVER_SYMBOL
udpsocket_recv_data(void)1244 static void udpsocket_recv_data(void)
1245 {
1246 u8 recv_data[512];
1247 u32 len = 0;
1248 u16 recv_length;
1249 struct sk_buff *skb;
1250
1251 RTKBT_DBG("-");
1252
1253 spin_lock(&btrtl_coex.spin_lock_sock);
1254 len = skb_queue_len(&btrtl_coex.sk->sk_receive_queue);
1255
1256 while (len > 0) {
1257 skb = skb_dequeue(&btrtl_coex.sk->sk_receive_queue);
1258
1259 /*important: cut the udp header from skb->data! header length is 8 byte */
1260 recv_length = skb->len - 8;
1261 memset(recv_data, 0, sizeof(recv_data));
1262 memcpy(recv_data, skb->data + 8, recv_length);
1263 //RTKBT_DBG("received data: %s :with len %u", recv_data, recv_length);
1264
1265 rtk_handle_event_from_wifi(recv_data);
1266
1267 len--;
1268 kfree_skb(skb);
1269 }
1270
1271 spin_unlock(&btrtl_coex.spin_lock_sock);
1272 }
1273
1274 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0)
udpsocket_recv(struct sock * sk,int bytes)1275 static void udpsocket_recv(struct sock *sk, int bytes)
1276 #else
1277 static void udpsocket_recv(struct sock *sk)
1278 #endif
1279 {
1280 spin_lock(&btrtl_coex.spin_lock_sock);
1281 btrtl_coex.sk = sk;
1282 spin_unlock(&btrtl_coex.spin_lock_sock);
1283 queue_delayed_work(btrtl_coex.sock_wq, &btrtl_coex.sock_work, 0);
1284 }
1285
create_udpsocket(void)1286 static void create_udpsocket(void)
1287 {
1288 int err;
1289 RTKBT_DBG("%s: connect_port: %d", __func__, CONNECT_PORT);
1290 btrtl_coex.sock_open = 0;
1291
1292 err = sock_create(AF_INET, SOCK_DGRAM, IPPROTO_UDP,
1293 &btrtl_coex.udpsock);
1294 if (err < 0) {
1295 RTKBT_ERR("%s: sock create error, err = %d", __func__, err);
1296 return;
1297 }
1298
1299 memset(&btrtl_coex.addr, 0, sizeof(struct sockaddr_in));
1300 btrtl_coex.addr.sin_family = AF_INET;
1301 btrtl_coex.addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1302 btrtl_coex.addr.sin_port = htons(CONNECT_PORT);
1303
1304 memset(&btrtl_coex.wifi_addr, 0, sizeof(struct sockaddr_in));
1305 btrtl_coex.wifi_addr.sin_family = AF_INET;
1306 btrtl_coex.wifi_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1307 btrtl_coex.wifi_addr.sin_port = htons(CONNECT_PORT_WIFI);
1308
1309 err =
1310 btrtl_coex.udpsock->ops->bind(btrtl_coex.udpsock,
1311 (struct sockaddr *)&btrtl_coex.
1312 addr, sizeof(struct sockaddr));
1313 if (err < 0) {
1314 sock_release(btrtl_coex.udpsock);
1315 RTKBT_ERR("%s: sock bind error, err = %d",__func__, err);
1316 return;
1317 }
1318
1319 btrtl_coex.sock_open = 1;
1320 btrtl_coex.udpsock->sk->sk_data_ready = udpsocket_recv;
1321 }
1322 #endif /* !RTK_COEX_OVER_SYMBOL */
1323
rtk_notify_extension_version_to_wifi(void)1324 static void rtk_notify_extension_version_to_wifi(void)
1325 {
1326 uint8_t para_length = 2;
1327 char p_buf[2 + HCI_CMD_PREAMBLE_SIZE];
1328 char *p = p_buf;
1329
1330 if (!btrtl_coex.wifi_on)
1331 return;
1332
1333 UINT16_TO_STREAM(p, HCI_OP_HCI_EXTENSION_VERSION_NOTIFY);
1334 *p++ = para_length;
1335 UINT16_TO_STREAM(p, HCI_EXTENSION_VERSION);
1336 RTKBT_DBG("extension version is 0x%x", HCI_EXTENSION_VERSION);
1337 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1338 RTKBT_ERR("%s: sock send error", __func__);
1339 }
1340
rtk_notify_btpatch_version_to_wifi(void)1341 static void rtk_notify_btpatch_version_to_wifi(void)
1342 {
1343 uint8_t para_length = 4;
1344 char p_buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1345 char *p = p_buf;
1346
1347 if (!btrtl_coex.wifi_on)
1348 return;
1349
1350 UINT16_TO_STREAM(p, HCI_OP_HCI_BT_PATCH_VER_NOTIFY);
1351 *p++ = para_length;
1352 UINT16_TO_STREAM(p, btrtl_coex.hci_reversion);
1353 UINT16_TO_STREAM(p, btrtl_coex.lmp_subversion);
1354 RTKBT_DBG("btpatch ver: len %u, hci_rev 0x%04x, lmp_subver 0x%04x",
1355 para_length, btrtl_coex.hci_reversion,
1356 btrtl_coex.lmp_subversion);
1357
1358 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1359 RTKBT_ERR("%s: sock send error", __func__);
1360 }
1361
rtk_notify_afhmap_to_wifi(void)1362 static void rtk_notify_afhmap_to_wifi(void)
1363 {
1364 uint8_t para_length = 13;
1365 char p_buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1366 char *p = p_buf;
1367 uint8_t kk = 0;
1368
1369 if (!btrtl_coex.wifi_on)
1370 return;
1371
1372 UINT16_TO_STREAM(p, HCI_OP_HCI_BT_AFH_MAP_NOTIFY);
1373 *p++ = para_length;
1374 *p++ = btrtl_coex.piconet_id;
1375 *p++ = btrtl_coex.mode;
1376 *p++ = 10;
1377 memcpy(p, btrtl_coex.afh_map, 10);
1378
1379 RTKBT_DBG("afhmap, piconet_id is 0x%x, map type is 0x%x",
1380 btrtl_coex.piconet_id, btrtl_coex.mode);
1381 for (kk = 0; kk < 10; kk++)
1382 RTKBT_DBG("afhmap data[%d] is 0x%x", kk,
1383 btrtl_coex.afh_map[kk]);
1384
1385 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1386 RTKBT_ERR("%s: sock send error", __func__);
1387 }
1388
rtk_notify_btcoex_to_wifi(uint8_t opcode,uint8_t status)1389 static void rtk_notify_btcoex_to_wifi(uint8_t opcode, uint8_t status)
1390 {
1391 uint8_t para_length = 2;
1392 char p_buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1393 char *p = p_buf;
1394
1395 if (!btrtl_coex.wifi_on)
1396 return;
1397
1398 UINT16_TO_STREAM(p, HCI_OP_HCI_BT_COEX_NOTIFY);
1399 *p++ = para_length;
1400 *p++ = opcode;
1401 if (!status)
1402 *p++ = 0;
1403 else
1404 *p++ = 1;
1405
1406 RTKBT_DBG("btcoex, opcode is 0x%x, status is 0x%x", opcode, status);
1407
1408 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1409 RTKBT_ERR("%s: sock send error", __func__);
1410 }
1411
rtk_notify_btoperation_to_wifi(uint8_t operation,uint8_t append_data_length,uint8_t * append_data)1412 static void rtk_notify_btoperation_to_wifi(uint8_t operation,
1413 uint8_t append_data_length,
1414 uint8_t * append_data)
1415 {
1416 uint8_t para_length = 3 + append_data_length;
1417 char p_buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1418 char *p = p_buf;
1419 uint8_t kk = 0;
1420
1421 if (!btrtl_coex.wifi_on)
1422 return;
1423
1424 UINT16_TO_STREAM(p, HCI_OP_BT_OPERATION_NOTIFY);
1425 *p++ = para_length;
1426 *p++ = operation;
1427 *p++ = append_data_length;
1428 if (append_data_length)
1429 memcpy(p, append_data, append_data_length);
1430
1431 RTKBT_DBG("btoperation: op 0x%02x, append_data_length %u",
1432 operation, append_data_length);
1433 if (append_data_length) {
1434 for (kk = 0; kk < append_data_length; kk++)
1435 RTKBT_DBG("append data is 0x%x", *(append_data + kk));
1436 }
1437
1438 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1439 RTKBT_ERR("%s: sock send error", __func__);
1440 }
1441
rtk_notify_info_to_wifi(uint8_t reason,uint8_t length,uint8_t * report_info)1442 static void rtk_notify_info_to_wifi(uint8_t reason, uint8_t length,
1443 uint8_t *report_info)
1444 {
1445 uint8_t para_length = 4 + length;
1446 char buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1447 char *p = buf;
1448 struct rtl_btinfo *report = (struct rtl_btinfo *)report_info;
1449
1450 if (length) {
1451 RTKBT_DBG("bt info: cmd %2.2X", report->cmd);
1452 RTKBT_DBG("bt info: len %2.2X", report->len);
1453 RTKBT_DBG("bt info: data %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X",
1454 report->data[0], report->data[1], report->data[2],
1455 report->data[3], report->data[4], report->data[5]);
1456 }
1457 RTKBT_DBG("bt info: reason 0x%2x, length 0x%2x", reason, length);
1458
1459 if (!btrtl_coex.wifi_on)
1460 return;
1461
1462 UINT16_TO_STREAM(p, HCI_OP_HCI_BT_INFO_NOTIFY);
1463 *p++ = para_length;
1464 *p++ = btrtl_coex.polling_enable;
1465 *p++ = btrtl_coex.polling_interval;
1466 *p++ = reason;
1467 *p++ = length;
1468
1469 if (length)
1470 memcpy(p, report_info, length);
1471
1472 RTKBT_DBG("para length %2x, polling_enable %u, poiiling_interval %u",
1473 para_length, btrtl_coex.polling_enable,
1474 btrtl_coex.polling_interval);
1475 /* send BT INFO to Wi-Fi driver */
1476 if (rtkbt_coexmsg_send(buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1477 RTKBT_ERR("%s: sock send error", __func__);
1478 }
1479
rtk_notify_regester_to_wifi(uint8_t * reg_value)1480 static void rtk_notify_regester_to_wifi(uint8_t * reg_value)
1481 {
1482 uint8_t para_length = 9;
1483 char p_buf[para_length + HCI_CMD_PREAMBLE_SIZE];
1484 char *p = p_buf;
1485 hci_mailbox_register *reg = (hci_mailbox_register *) reg_value;
1486
1487 if (!btrtl_coex.wifi_on)
1488 return;
1489
1490 UINT16_TO_STREAM(p, HCI_OP_HCI_BT_REGISTER_VALUE_NOTIFY);
1491 *p++ = para_length;
1492 memcpy(p, reg_value, para_length);
1493
1494 RTKBT_DBG("bt register, register type is %x", reg->type);
1495 RTKBT_DBG("bt register, register offset is %x", reg->offset);
1496 RTKBT_DBG("bt register, register value is %x", reg->value);
1497
1498 if (rtkbt_coexmsg_send(p_buf, para_length + HCI_CMD_PREAMBLE_SIZE) < 0)
1499 RTKBT_ERR("%s: sock send error", __func__);
1500 }
1501
1502 #endif
1503
rtk_btcoex_parse_cmd(uint8_t * buffer,int count)1504 void rtk_btcoex_parse_cmd(uint8_t *buffer, int count)
1505 {
1506 u16 opcode = (buffer[0]) + (buffer[1] << 8);
1507
1508 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
1509 RTKBT_INFO("%s: Coex is closed, ignore", __func__);
1510 return;
1511 }
1512
1513 switch (opcode) {
1514 case HCI_OP_INQUIRY:
1515 case HCI_OP_PERIODIC_INQ:
1516 if (!btrtl_coex.isinquirying) {
1517 btrtl_coex.isinquirying = 1;
1518 #ifdef RTB_SOFTWARE_MAILBOX
1519 RTKBT_DBG("hci (periodic)inq, notify wifi "
1520 "inquiry start");
1521 rtk_notify_btoperation_to_wifi(BT_OPCODE_INQUIRY_START,
1522 0, NULL);
1523 #else
1524 RTKBT_INFO("hci (periodic)inq start");
1525 #endif
1526 }
1527 break;
1528 case HCI_OP_INQUIRY_CANCEL:
1529 case HCI_OP_EXIT_PERIODIC_INQ:
1530 if (btrtl_coex.isinquirying) {
1531 btrtl_coex.isinquirying = 0;
1532 #ifdef RTB_SOFTWARE_MAILBOX
1533 RTKBT_DBG("hci (periodic)inq cancel/exit, notify wifi "
1534 "inquiry stop");
1535 rtk_notify_btoperation_to_wifi(BT_OPCODE_INQUIRY_END, 0,
1536 NULL);
1537 #else
1538 RTKBT_INFO("hci (periodic)inq cancel/exit");
1539 #endif
1540 }
1541 break;
1542 case HCI_OP_ACCEPT_CONN_REQ:
1543 if (!btrtl_coex.ispaging) {
1544 btrtl_coex.ispaging = 1;
1545 #ifdef RTB_SOFTWARE_MAILBOX
1546 RTKBT_DBG("hci accept connreq, notify wifi page start");
1547 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAGE_START, 0,
1548 NULL);
1549 #else
1550 RTKBT_INFO("hci accept conn req");
1551 #endif
1552 }
1553 break;
1554 case HCI_OP_DISCONNECT:
1555 RTKBT_INFO("HCI Disconnect, handle %04x, reason 0x%02x",
1556 ((u16)buffer[4] << 8 | buffer[3]), buffer[5]);
1557 break;
1558 default:
1559 break;
1560 }
1561 }
1562
rtk_handle_inquiry_complete(void)1563 static void rtk_handle_inquiry_complete(void)
1564 {
1565 if (btrtl_coex.isinquirying) {
1566 btrtl_coex.isinquirying = 0;
1567 #ifdef RTB_SOFTWARE_MAILBOX
1568 RTKBT_DBG("inq complete, notify wifi inquiry end");
1569 rtk_notify_btoperation_to_wifi(BT_OPCODE_INQUIRY_END, 0, NULL);
1570 #else
1571 RTKBT_INFO("inquiry complete");
1572 #endif
1573 }
1574 }
1575
rtk_handle_pin_code_req(void)1576 static void rtk_handle_pin_code_req(void)
1577 {
1578 if (!btrtl_coex.ispairing) {
1579 btrtl_coex.ispairing = 1;
1580 #ifdef RTB_SOFTWARE_MAILBOX
1581 RTKBT_DBG("pin code req, notify wifi pair start");
1582 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAIR_START, 0, NULL);
1583 #else
1584 RTKBT_INFO("pin code request");
1585 #endif
1586 }
1587 }
1588
rtk_handle_io_capa_req(void)1589 static void rtk_handle_io_capa_req(void)
1590 {
1591 if (!btrtl_coex.ispairing) {
1592 btrtl_coex.ispairing = 1;
1593 #ifdef RTB_SOFTWARE_MAILBOX
1594 RTKBT_DBG("io cap req, notify wifi pair start");
1595 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAIR_START, 0, NULL);
1596 #else
1597 RTKBT_INFO("io capability request");
1598 #endif
1599 }
1600 }
1601
rtk_handle_auth_request(void)1602 static void rtk_handle_auth_request(void)
1603 {
1604 if (btrtl_coex.ispairing) {
1605 btrtl_coex.ispairing = 0;
1606 #ifdef RTB_SOFTWARE_MAILBOX
1607 RTKBT_DBG("auth req, notify wifi pair end");
1608 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAIR_END, 0, NULL);
1609 #else
1610 RTKBT_INFO("authentication request");
1611 #endif
1612 }
1613 }
1614
rtk_handle_link_key_notify(void)1615 static void rtk_handle_link_key_notify(void)
1616 {
1617 if (btrtl_coex.ispairing) {
1618 btrtl_coex.ispairing = 0;
1619 #ifdef RTB_SOFTWARE_MAILBOX
1620 RTKBT_DBG("link key notify, notify wifi pair end");
1621 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAIR_END, 0, NULL);
1622 #else
1623 RTKBT_INFO("link key notify");
1624 #endif
1625 }
1626 }
1627
rtk_handle_mode_change_evt(u8 * p)1628 static void rtk_handle_mode_change_evt(u8 * p)
1629 {
1630 u16 mode_change_handle, mode_interval;
1631
1632 p++;
1633 STREAM_TO_UINT16(mode_change_handle, p);
1634 p++;
1635 STREAM_TO_UINT16(mode_interval, p);
1636 update_hid_active_state(mode_change_handle, mode_interval);
1637 }
1638
1639 #ifdef RTB_SOFTWARE_MAILBOX
rtk_parse_vendor_mailbox_cmd_evt(u8 * p,u8 total_len)1640 static void rtk_parse_vendor_mailbox_cmd_evt(u8 * p, u8 total_len)
1641 {
1642 u8 status, subcmd;
1643 u8 temp_cmd[10];
1644
1645 status = *p++;
1646 if (total_len <= 4) {
1647 RTKBT_DBG("receive mailbox cmd from fw, total length <= 4");
1648 return;
1649 }
1650 subcmd = *p++;
1651 RTKBT_DBG("receive mailbox cmd from fw, subcmd is 0x%x, status is 0x%x",
1652 subcmd, status);
1653
1654 switch (subcmd) {
1655 case HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO:
1656 if (status == 0) //success
1657 rtk_notify_info_to_wifi(POLLING_RESPONSE,
1658 RTL_BTINFO_LEN, (uint8_t *)p);
1659 break;
1660
1661 case HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD:
1662 rtk_notify_btcoex_to_wifi(WIFI_BW_CHNL_NOTIFY, status);
1663 break;
1664
1665 case HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD:
1666 rtk_notify_btcoex_to_wifi(BT_POWER_DECREASE_CONTROL, status);
1667 break;
1668
1669 case HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD:
1670 rtk_notify_btcoex_to_wifi(IGNORE_WLAN_ACTIVE_CONTROL, status);
1671 break;
1672
1673 case HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE:
1674 rtk_notify_btcoex_to_wifi(BT_PSD_MODE_CONTROL, status);
1675 break;
1676
1677 case HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT:
1678 rtk_notify_btcoex_to_wifi(LNA_CONSTRAIN_CONTROL, status);
1679 break;
1680
1681 case HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE:
1682 break;
1683
1684 case HCI_VENDOR_SUB_CMD_BT_SET_TXRETRY_REPORT_PARAM:
1685 break;
1686
1687 case HCI_VENDOR_SUB_CMD_BT_SET_PTATABLE:
1688 break;
1689
1690 case HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L:
1691 if (status == 0) {
1692 memcpy(btrtl_coex.afh_map, p + 4, 4); /* cmd_idx, length, piconet_id, mode */
1693 temp_cmd[0] = HCI_VENDOR_SUB_CMD_GET_AFH_MAP_M;
1694 temp_cmd[1] = 2;
1695 temp_cmd[2] = btrtl_coex.piconet_id;
1696 temp_cmd[3] = btrtl_coex.mode;
1697 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4,
1698 temp_cmd);
1699 } else {
1700 memset(btrtl_coex.afh_map, 0, 10);
1701 rtk_notify_afhmap_to_wifi();
1702 }
1703 break;
1704
1705 case HCI_VENDOR_SUB_CMD_GET_AFH_MAP_M:
1706 if (status == 0) {
1707 memcpy(btrtl_coex.afh_map + 4, p + 4, 4);
1708 temp_cmd[0] = HCI_VENDOR_SUB_CMD_GET_AFH_MAP_H;
1709 temp_cmd[1] = 2;
1710 temp_cmd[2] = btrtl_coex.piconet_id;
1711 temp_cmd[3] = btrtl_coex.mode;
1712 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4,
1713 temp_cmd);
1714 } else {
1715 memset(btrtl_coex.afh_map, 0, 10);
1716 rtk_notify_afhmap_to_wifi();
1717 }
1718 break;
1719
1720 case HCI_VENDOR_SUB_CMD_GET_AFH_MAP_H:
1721 if (status == 0)
1722 memcpy(btrtl_coex.afh_map + 8, p + 4, 2);
1723 else
1724 memset(btrtl_coex.afh_map, 0, 10);
1725
1726 rtk_notify_afhmap_to_wifi();
1727 break;
1728
1729 case HCI_VENDOR_SUB_CMD_RD_REG_REQ:
1730 if (status == 0)
1731 rtk_notify_regester_to_wifi(p + 3); /* cmd_idx,length,regist type */
1732 break;
1733
1734 case HCI_VENDOR_SUB_CMD_WR_REG_REQ:
1735 rtk_notify_btcoex_to_wifi(BT_REGISTER_ACCESS, status);
1736 break;
1737
1738 default:
1739 break;
1740 }
1741 }
1742 #endif /* RTB_SOFTWARE_MAILBOX */
1743
rtk_handle_cmd_complete_evt(u8 total_len,u8 * p)1744 static void rtk_handle_cmd_complete_evt(u8 total_len, u8 * p)
1745 {
1746 u16 opcode;
1747
1748 p++;
1749 STREAM_TO_UINT16(opcode, p);
1750 //RTKBT_DBG("cmd_complete, opcode is 0x%x", opcode);
1751
1752 if (opcode == HCI_OP_PERIODIC_INQ) {
1753 if (*p++ && btrtl_coex.isinquirying) {
1754 btrtl_coex.isinquirying = 0;
1755 #ifdef RTB_SOFTWARE_MAILBOX
1756 RTKBT_DBG("hci period inq, start error, notify wifi "
1757 "inquiry stop");
1758 rtk_notify_btoperation_to_wifi(BT_OPCODE_INQUIRY_END, 0,
1759 NULL);
1760 #else
1761 RTKBT_INFO("hci period inquiry start error");
1762 #endif
1763 }
1764 }
1765
1766 if (opcode == HCI_OP_READ_LOCAL_VERSION) {
1767 if (!(*p++)) {
1768 p++;
1769 STREAM_TO_UINT16(btrtl_coex.hci_reversion, p);
1770 p += 3;
1771 STREAM_TO_UINT16(btrtl_coex.lmp_subversion, p);
1772 RTKBT_DBG("BTCOEX hci_rev 0x%04x",
1773 btrtl_coex.hci_reversion);
1774 RTKBT_DBG("BTCOEX lmp_subver 0x%04x",
1775 btrtl_coex.lmp_subversion);
1776 }
1777 }
1778
1779 #ifdef RTB_SOFTWARE_MAILBOX
1780 if (opcode == HCI_VENDOR_MAILBOX_CMD) {
1781 rtk_parse_vendor_mailbox_cmd_evt(p, total_len);
1782 }
1783 #endif
1784 }
1785
rtk_handle_cmd_status_evt(u8 * p)1786 static void rtk_handle_cmd_status_evt(u8 * p)
1787 {
1788 u16 opcode;
1789 u8 status;
1790
1791 status = *p++;
1792 p++;
1793 STREAM_TO_UINT16(opcode, p);
1794 //RTKBT_DBG("cmd_status, opcode is 0x%x", opcode);
1795 if ((opcode == HCI_OP_INQUIRY) && (status)) {
1796 if (btrtl_coex.isinquirying) {
1797 btrtl_coex.isinquirying = 0;
1798 #ifdef RTB_SOFTWARE_MAILBOX
1799 RTKBT_DBG("hci inq, start error, notify wifi inq stop");
1800 rtk_notify_btoperation_to_wifi(BT_OPCODE_INQUIRY_END, 0,
1801 NULL);
1802 #else
1803 RTKBT_INFO("hci inquiry start error");
1804 #endif
1805 }
1806 }
1807
1808 if (opcode == HCI_OP_CREATE_CONN) {
1809 if (!status && !btrtl_coex.ispaging) {
1810 btrtl_coex.ispaging = 1;
1811 #ifdef RTB_SOFTWARE_MAILBOX
1812 RTKBT_DBG("hci create conn, notify wifi start page");
1813 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAGE_START, 0,
1814 NULL);
1815 #else
1816 RTKBT_INFO("hci create connection, start paging");
1817 #endif
1818 }
1819 }
1820 }
1821
rtk_handle_connection_complete_evt(u8 * p)1822 static void rtk_handle_connection_complete_evt(u8 * p)
1823 {
1824 u16 handle;
1825 u8 status, link_type;
1826 rtk_conn_prof *hci_conn = NULL;
1827
1828 status = *p++;
1829 STREAM_TO_UINT16(handle, p);
1830 p += 6;
1831 link_type = *p++;
1832
1833 RTKBT_INFO("connected, handle %04x, status 0x%02x", handle, status);
1834
1835 if (status == 0) {
1836 if (btrtl_coex.ispaging) {
1837 btrtl_coex.ispaging = 0;
1838 #ifdef RTB_SOFTWARE_MAILBOX
1839 RTKBT_DBG("notify wifi page success end");
1840 rtk_notify_btoperation_to_wifi
1841 (BT_OPCODE_PAGE_SUCCESS_END, 0, NULL);
1842 #else
1843 RTKBT_INFO("Page success");
1844 #endif
1845 }
1846
1847 hci_conn = find_connection_by_handle(&btrtl_coex, handle);
1848 if (hci_conn == NULL) {
1849 hci_conn = allocate_connection_by_handle(handle);
1850 if (hci_conn) {
1851 add_connection_to_hash(&btrtl_coex,
1852 hci_conn);
1853 hci_conn->profile_bitmap = 0;
1854 memset(hci_conn->profile_refcount, 0, 8);
1855 if ((0 == link_type) || (2 == link_type)) { //sco or esco
1856 hci_conn->type = 1;
1857 update_profile_connection(hci_conn,
1858 profile_sco,
1859 TRUE);
1860 } else
1861 hci_conn->type = 0;
1862 } else {
1863 RTKBT_ERR("hci connection allocate fail");
1864 }
1865 } else {
1866 RTKBT_DBG("hci conn handle 0x%04x already existed!",
1867 handle);
1868 hci_conn->profile_bitmap = 0;
1869 memset(hci_conn->profile_refcount, 0, 8);
1870 if ((0 == link_type) || (2 == link_type)) { //sco or esco
1871 hci_conn->type = 1;
1872 update_profile_connection(hci_conn, profile_sco,
1873 TRUE);
1874 } else
1875 hci_conn->type = 0;
1876 }
1877 } else if (btrtl_coex.ispaging) {
1878 btrtl_coex.ispaging = 0;
1879 #ifdef RTB_SOFTWARE_MAILBOX
1880 RTKBT_DBG("notify wifi page unsuccess end");
1881 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAGE_UNSUCCESS_END, 0,
1882 NULL);
1883 #else
1884 RTKBT_INFO("Page failed");
1885 #endif
1886 }
1887 }
1888
rtk_handle_le_connection_complete_evt(u8 enhanced,u8 * p)1889 static void rtk_handle_le_connection_complete_evt(u8 enhanced, u8 * p)
1890 {
1891 u16 handle, interval;
1892 u8 status;
1893 rtk_conn_prof *hci_conn = NULL;
1894
1895 status = *p++;
1896 STREAM_TO_UINT16(handle, p);
1897 if (!enhanced)
1898 p += 8; /* role, address type, address */
1899 else
1900 p += (8 + 12); /* plus two bluetooth addresses */
1901 STREAM_TO_UINT16(interval, p);
1902
1903 RTKBT_INFO("LE connected, handle %04x, status 0x%02x, interval %u",
1904 handle, status, interval);
1905
1906 if (status == 0) {
1907 if (btrtl_coex.ispaging) {
1908 btrtl_coex.ispaging = 0;
1909 #ifdef RTB_SOFTWARE_MAILBOX
1910 RTKBT_DBG("notify wifi page success end");
1911 rtk_notify_btoperation_to_wifi
1912 (BT_OPCODE_PAGE_SUCCESS_END, 0, NULL);
1913 #else
1914 RTKBT_INFO("Page success end");
1915 #endif
1916 }
1917
1918 hci_conn = find_connection_by_handle(&btrtl_coex, handle);
1919 if (hci_conn == NULL) {
1920 hci_conn = allocate_connection_by_handle(handle);
1921 if (hci_conn) {
1922 add_connection_to_hash(&btrtl_coex,
1923 hci_conn);
1924 hci_conn->profile_bitmap = 0;
1925 memset(hci_conn->profile_refcount, 0, 8);
1926 hci_conn->type = 2;
1927 update_profile_connection(hci_conn, profile_hid, TRUE); //for coex, le is the same as hid
1928 update_hid_active_state(handle, interval);
1929 } else {
1930 RTKBT_ERR("hci connection allocate fail");
1931 }
1932 } else {
1933 RTKBT_DBG("hci conn handle 0x%04x already existed!",
1934 handle);
1935 hci_conn->profile_bitmap = 0;
1936 memset(hci_conn->profile_refcount, 0, 8);
1937 hci_conn->type = 2;
1938 update_profile_connection(hci_conn, profile_hid, TRUE);
1939 update_hid_active_state(handle, interval);
1940 }
1941 } else if (btrtl_coex.ispaging) {
1942 btrtl_coex.ispaging = 0;
1943 #ifdef RTB_SOFTWARE_MAILBOX
1944 RTKBT_DBG("notify wifi page unsuccess end");
1945 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAGE_UNSUCCESS_END, 0,
1946 NULL);
1947 #else
1948 RTKBT_INFO("Page failed");
1949 #endif
1950 }
1951 }
1952
rtk_handle_le_connection_update_complete_evt(u8 * p)1953 static void rtk_handle_le_connection_update_complete_evt(u8 * p)
1954 {
1955 u16 handle, interval;
1956 /* u8 status; */
1957
1958 /* status = *p++; */
1959 p++;
1960
1961 STREAM_TO_UINT16(handle, p);
1962 STREAM_TO_UINT16(interval, p);
1963 update_hid_active_state(handle, interval);
1964 }
1965
rtk_handle_le_meta_evt(u8 * p)1966 static void rtk_handle_le_meta_evt(u8 * p)
1967 {
1968 u8 sub_event = *p++;
1969 switch (sub_event) {
1970 case HCI_EV_LE_CONN_COMPLETE:
1971 rtk_handle_le_connection_complete_evt(0, p);
1972 break;
1973 case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
1974 rtk_handle_le_connection_complete_evt(1, p);
1975 break;
1976
1977 case HCI_EV_LE_CONN_UPDATE_COMPLETE:
1978 rtk_handle_le_connection_update_complete_evt(p);
1979 break;
1980
1981 default:
1982 break;
1983 }
1984 }
1985
disconn_profile(struct rtl_hci_conn * conn,u8 pfe_index)1986 static u8 disconn_profile(struct rtl_hci_conn *conn, u8 pfe_index)
1987 {
1988 u8 need_update = 0;
1989
1990 if (!btrtl_coex.profile_refcount[pfe_index]) {
1991 RTKBT_WARN("profile %u ref is 0", pfe_index);
1992 return 0;
1993 }
1994
1995 btrtl_coex.profile_refcount[pfe_index]--;
1996 RTKBT_INFO("%s: profile_ref[%u] %u", __func__, pfe_index,
1997 btrtl_coex.profile_refcount[pfe_index]);
1998
1999 if (!btrtl_coex.profile_refcount[pfe_index]) {
2000 need_update = 1;
2001 btrtl_coex.profile_bitmap &= ~(BIT(pfe_index));
2002
2003 /* if profile does not exist, status is meaningless */
2004 btrtl_coex.profile_status &= ~(BIT(pfe_index));
2005 rtk_check_del_timer(pfe_index);
2006 }
2007
2008 if (conn->profile_refcount[pfe_index])
2009 conn->profile_refcount[pfe_index]--;
2010 else
2011 RTKBT_INFO("%s: conn pfe ref[%u] is 0", __func__,
2012 conn->profile_refcount[pfe_index]);
2013 if (!conn->profile_refcount[pfe_index]) {
2014 need_update = 1;
2015 conn->profile_bitmap &= ~(BIT(pfe_index));
2016
2017 /* clear profile_hid_interval if need */
2018 if ((profile_hid == pfe_index) &&
2019 (conn->profile_bitmap & (BIT(profile_hid_interval)))) {
2020 conn->profile_bitmap &= ~(BIT(profile_hid_interval));
2021 if (btrtl_coex.profile_refcount[profile_hid_interval])
2022 btrtl_coex.profile_refcount[profile_hid_interval]--;
2023 }
2024 }
2025
2026 return need_update;
2027 }
2028
disconn_acl(u16 handle,struct rtl_hci_conn * conn)2029 static void disconn_acl(u16 handle, struct rtl_hci_conn *conn)
2030 {
2031 struct rtl_coex_struct *coex = &btrtl_coex;
2032 rtk_prof_info *prof_info = NULL;
2033 struct list_head *iter = NULL, *temp = NULL;
2034 u8 need_update = 0;
2035
2036 spin_lock(&coex->spin_lock_profile);
2037
2038 list_for_each_safe(iter, temp, &coex->profile_list) {
2039 prof_info = list_entry(iter, rtk_prof_info, list);
2040 if (handle == prof_info->handle) {
2041 RTKBT_DBG("hci disconn, hndl %x, psm %x, dcid %x, "
2042 "scid %x, profile %u", prof_info->handle,
2043 prof_info->psm, prof_info->dcid,
2044 prof_info->scid, prof_info->profile_index);
2045 //If both scid and dcid > 0, L2cap connection is exist.
2046 need_update |= disconn_profile(conn,
2047 prof_info->profile_index);
2048 if ((prof_info->flags & A2DP_MEDIA) &&
2049 (conn->profile_bitmap & BIT(profile_sink)))
2050 need_update |= disconn_profile(conn,
2051 profile_sink);
2052 delete_profile_from_hash(prof_info);
2053 }
2054 }
2055 if (need_update)
2056 rtk_notify_profileinfo_to_fw();
2057 spin_unlock(&coex->spin_lock_profile);
2058 }
2059
rtk_handle_disconnect_complete_evt(u8 * p)2060 static void rtk_handle_disconnect_complete_evt(u8 * p)
2061 {
2062 u16 handle;
2063 u8 status;
2064 u8 reason;
2065 rtk_conn_prof *hci_conn = NULL;
2066
2067 if (btrtl_coex.ispairing) { //for slave: connection will be disconnected if authentication fail
2068 btrtl_coex.ispairing = 0;
2069 #ifdef RTB_SOFTWARE_MAILBOX
2070 RTKBT_DBG("hci disc complete, notify wifi pair end");
2071 rtk_notify_btoperation_to_wifi(BT_OPCODE_PAIR_END, 0, NULL);
2072 #else
2073 RTKBT_INFO("hci disconnection complete");
2074 #endif
2075 }
2076
2077 status = *p++;
2078 STREAM_TO_UINT16(handle, p);
2079 reason = *p;
2080
2081 RTKBT_INFO("disconn cmpl evt: status 0x%02x, handle %04x, reason 0x%02x",
2082 status, handle, reason);
2083
2084 if (status == 0) {
2085 RTKBT_DBG("process disconn complete event.");
2086 hci_conn = find_connection_by_handle(&btrtl_coex, handle);
2087 if (hci_conn) {
2088 switch (hci_conn->type) {
2089 case 0:
2090 /* FIXME: If this is interrupted by l2cap rx,
2091 * there may be deadlock on spin_lock_profile */
2092 disconn_acl(handle, hci_conn);
2093 break;
2094
2095 case 1:
2096 update_profile_connection(hci_conn, profile_sco,
2097 FALSE);
2098 break;
2099
2100 case 2:
2101 update_profile_connection(hci_conn, profile_hid,
2102 FALSE);
2103 break;
2104
2105 default:
2106 break;
2107 }
2108 delete_connection_from_hash(hci_conn);
2109 } else
2110 RTKBT_ERR("hci conn handle 0x%04x not found", handle);
2111 }
2112 }
2113
rtk_handle_specific_evt(u8 * p)2114 static void rtk_handle_specific_evt(u8 * p)
2115 {
2116 u16 subcode;
2117
2118 STREAM_TO_UINT16(subcode, p);
2119 if (subcode == HCI_VENDOR_PTA_AUTO_REPORT_EVENT) {
2120 #ifdef RTB_SOFTWARE_MAILBOX
2121 RTKBT_DBG("notify wifi driver with autoreport data");
2122 rtk_notify_info_to_wifi(AUTO_REPORT, RTL_BTINFO_LEN,
2123 (uint8_t *)p);
2124 #else
2125 RTKBT_INFO("auto report data");
2126 #endif
2127 }
2128 }
2129
rtk_parse_event_data(struct rtl_coex_struct * coex,u8 * data,u16 len)2130 static void rtk_parse_event_data(struct rtl_coex_struct *coex,
2131 u8 *data, u16 len)
2132 {
2133 u8 *p = data;
2134 u8 event_code = *p++;
2135 u8 total_len = *p++;
2136
2137 (void)coex;
2138 (void)&len;
2139
2140 switch (event_code) {
2141 case HCI_EV_INQUIRY_COMPLETE:
2142 rtk_handle_inquiry_complete();
2143 break;
2144
2145 case HCI_EV_PIN_CODE_REQ:
2146 rtk_handle_pin_code_req();
2147 break;
2148
2149 case HCI_EV_IO_CAPA_REQUEST:
2150 rtk_handle_io_capa_req();
2151 break;
2152
2153 case HCI_EV_AUTH_COMPLETE:
2154 rtk_handle_auth_request();
2155 break;
2156
2157 case HCI_EV_LINK_KEY_NOTIFY:
2158 rtk_handle_link_key_notify();
2159 break;
2160
2161 case HCI_EV_MODE_CHANGE:
2162 rtk_handle_mode_change_evt(p);
2163 break;
2164
2165 case HCI_EV_CMD_COMPLETE:
2166 rtk_handle_cmd_complete_evt(total_len, p);
2167 break;
2168
2169 case HCI_EV_CMD_STATUS:
2170 rtk_handle_cmd_status_evt(p);
2171 break;
2172
2173 case HCI_EV_CONN_COMPLETE:
2174 case HCI_EV_SYNC_CONN_COMPLETE:
2175 rtk_handle_connection_complete_evt(p);
2176 break;
2177
2178 case HCI_EV_DISCONN_COMPLETE:
2179 rtk_handle_disconnect_complete_evt(p);
2180 break;
2181
2182 case HCI_EV_LE_META:
2183 rtk_handle_le_meta_evt(p);
2184 break;
2185
2186 case HCI_EV_VENDOR_SPECIFIC:
2187 rtk_handle_specific_evt(p);
2188 break;
2189
2190 default:
2191 break;
2192 }
2193 }
2194
2195 const char l2_dir_str[][4] = {
2196 "RX", "TX",
2197 };
2198
rtl_process_l2_sig(struct rtl_l2_buff * l2)2199 void rtl_process_l2_sig(struct rtl_l2_buff *l2)
2200 {
2201 /* u8 flag; */
2202 u8 code;
2203 /* u8 identifier; */
2204 u16 handle;
2205 /* u16 total_len; */
2206 /* u16 pdu_len, channel_id; */
2207 /* u16 command_len; */
2208 u16 psm, scid, dcid, result;
2209 /* u16 status; */
2210 u8 *pp = l2->data;
2211
2212 STREAM_TO_UINT16(handle, pp);
2213 /* flag = handle >> 12; */
2214 handle = handle & 0x0FFF;
2215 /* STREAM_TO_UINT16(total_len, pp); */
2216 pp += 2; /* data total length */
2217
2218 /* STREAM_TO_UINT16(pdu_len, pp);
2219 * STREAM_TO_UINT16(channel_id, pp); */
2220 pp += 4; /* l2 len and channel id */
2221
2222 code = *pp++;
2223 switch (code) {
2224 case L2CAP_CONN_REQ:
2225 /* identifier = *pp++; */
2226 pp++;
2227 /* STREAM_TO_UINT16(command_len, pp); */
2228 pp += 2;
2229 STREAM_TO_UINT16(psm, pp);
2230 STREAM_TO_UINT16(scid, pp);
2231 RTKBT_DBG("%s l2cap conn req, hndl 0x%04x, PSM 0x%04x, "
2232 "scid 0x%04x", l2_dir_str[l2->out], handle, psm,
2233 scid);
2234 handle_l2cap_con_req(handle, psm, scid, l2->out);
2235 break;
2236
2237 case L2CAP_CONN_RSP:
2238 /* identifier = *pp++; */
2239 pp++;
2240 /* STREAM_TO_UINT16(command_len, pp); */
2241 pp += 2;
2242 STREAM_TO_UINT16(dcid, pp);
2243 STREAM_TO_UINT16(scid, pp);
2244 STREAM_TO_UINT16(result, pp);
2245 /* STREAM_TO_UINT16(status, pp); */
2246 pp += 2;
2247 RTKBT_DBG("%s l2cap conn rsp, hndl 0x%04x, dcid 0x%04x, "
2248 "scid 0x%04x, result 0x%04x", l2_dir_str[l2->out],
2249 handle, dcid, scid, result);
2250 handle_l2cap_con_rsp(handle, dcid, scid, l2->out, result);
2251 break;
2252
2253 case L2CAP_DISCONN_REQ:
2254 /* identifier = *pp++; */
2255 pp++;
2256 /* STREAM_TO_UINT16(command_len, pp); */
2257 pp += 2;
2258 STREAM_TO_UINT16(dcid, pp);
2259 STREAM_TO_UINT16(scid, pp);
2260 RTKBT_DBG("%s l2cap disconn req, hndl 0x%04x, dcid 0x%04x, "
2261 "scid 0x%04x", l2_dir_str[l2->out], handle, dcid, scid);
2262 handle_l2cap_discon_req(handle, dcid, scid, l2->out);
2263 break;
2264 default:
2265 RTKBT_DBG("undesired l2 command %u", code);
2266 break;
2267 }
2268 }
2269
rtl_l2_data_process(u8 * pp,u16 len,int dir)2270 static void rtl_l2_data_process(u8 *pp, u16 len, int dir)
2271 {
2272 u8 code;
2273 u8 flag;
2274 u16 handle, pdu_len, channel_id;
2275 /* u16 total_len; */
2276 struct rtl_l2_buff *l2 = NULL;
2277 u8 *hd = pp;
2278
2279 /* RTKBT_DBG("l2 sig data %p, len %u, dir %d", pp, len, dir); */
2280
2281 STREAM_TO_UINT16(handle, pp);
2282 flag = handle >> 12;
2283 handle = handle & 0x0FFF;
2284 /* STREAM_TO_UINT16(total_len, pp); */
2285 pp += 2; /* data total length */
2286
2287 STREAM_TO_UINT16(pdu_len, pp);
2288 STREAM_TO_UINT16(channel_id, pp);
2289
2290 if (channel_id == 0x0001) {
2291 code = *pp++;
2292 switch (code) {
2293 case L2CAP_CONN_REQ:
2294 case L2CAP_CONN_RSP:
2295 case L2CAP_DISCONN_REQ:
2296 RTKBT_DBG("l2cap op %u, len %u, out %d", code, len,
2297 dir);
2298 l2 = rtl_l2_node_get(&btrtl_coex);
2299 if (l2) {
2300 u16 n;
2301 n = min_t(uint, len, L2_MAX_SUBSEC_LEN);
2302 memcpy(l2->data, hd, n);
2303 l2->out = dir;
2304 rtl_l2_node_to_used(&btrtl_coex, l2);
2305 queue_delayed_work(btrtl_coex.fw_wq,
2306 &btrtl_coex.l2_work, 0);
2307 } else
2308 RTKBT_ERR("%s: failed to get l2 node",
2309 __func__);
2310 break;
2311 case L2CAP_DISCONN_RSP:
2312 break;
2313 default:
2314 break;
2315 }
2316 } else {
2317 if ((flag != 0x01) && (is_profile_connected(profile_a2dp) ||
2318 is_profile_connected(profile_pan)))
2319 /* Do not count the continuous packets */
2320 packets_count(handle, channel_id, pdu_len, dir, pp);
2321 }
2322 return;
2323 }
2324
2325
rtl_l2_work(struct work_struct * work)2326 static void rtl_l2_work(struct work_struct *work)
2327 {
2328 struct rtl_coex_struct *coex;
2329 struct rtl_l2_buff *l2;
2330 unsigned long flags;
2331
2332 coex = container_of(work, struct rtl_coex_struct, l2_work.work);
2333
2334 spin_lock_irqsave(&coex->buff_lock, flags);
2335 while (!list_empty(&coex->l2_used_list)) {
2336 l2 = list_entry(coex->l2_used_list.next, struct rtl_l2_buff,
2337 list);
2338 list_del(&l2->list);
2339
2340 spin_unlock_irqrestore(&coex->buff_lock, flags);
2341
2342 rtl_process_l2_sig(l2);
2343
2344 spin_lock_irqsave(&coex->buff_lock, flags);
2345
2346 list_add_tail(&l2->list, &coex->l2_free_list);
2347 }
2348 spin_unlock_irqrestore(&coex->buff_lock, flags);
2349
2350 return;
2351 }
2352
rtl_ev_work(struct work_struct * work)2353 static void rtl_ev_work(struct work_struct *work)
2354 {
2355 struct rtl_coex_struct *coex;
2356 struct rtl_hci_ev *ev;
2357 unsigned long flags;
2358
2359 coex = container_of(work, struct rtl_coex_struct, fw_work.work);
2360
2361 spin_lock_irqsave(&coex->buff_lock, flags);
2362 while (!list_empty(&coex->ev_used_list)) {
2363 ev = list_entry(coex->ev_used_list.next, struct rtl_hci_ev,
2364 list);
2365 list_del(&ev->list);
2366 spin_unlock_irqrestore(&coex->buff_lock, flags);
2367
2368 rtk_parse_event_data(coex, ev->data, ev->len);
2369
2370 spin_lock_irqsave(&coex->buff_lock, flags);
2371 list_add_tail(&ev->list, &coex->ev_free_list);
2372 }
2373 spin_unlock_irqrestore(&coex->buff_lock, flags);
2374 }
2375
cmd_cmplt_filter_out(u8 * buf)2376 static inline int cmd_cmplt_filter_out(u8 *buf)
2377 {
2378 u16 opcode;
2379
2380 opcode = buf[3] | (buf[4] << 8);
2381 switch (opcode) {
2382 case HCI_OP_PERIODIC_INQ:
2383 case HCI_OP_READ_LOCAL_VERSION:
2384 #ifdef RTB_SOFTWARE_MAILBOX
2385 case HCI_VENDOR_MAILBOX_CMD:
2386 #endif
2387 return 0;
2388 default:
2389 return 1;
2390 }
2391 }
2392
cmd_status_filter_out(u8 * buf)2393 static inline int cmd_status_filter_out(u8 *buf)
2394 {
2395 u16 opcode;
2396
2397 opcode = buf[4] | (buf[5] << 8);
2398 switch (opcode) {
2399 case HCI_OP_INQUIRY:
2400 case HCI_OP_CREATE_CONN:
2401 return 0;
2402 default:
2403 return 1;
2404 }
2405 }
2406
ev_filter_out(u8 * buf)2407 int ev_filter_out(u8 *buf)
2408 {
2409 switch (buf[0]) {
2410 case HCI_EV_INQUIRY_COMPLETE:
2411 case HCI_EV_PIN_CODE_REQ:
2412 case HCI_EV_IO_CAPA_REQUEST:
2413 case HCI_EV_AUTH_COMPLETE:
2414 case HCI_EV_LINK_KEY_NOTIFY:
2415 case HCI_EV_MODE_CHANGE:
2416 case HCI_EV_CONN_COMPLETE:
2417 case HCI_EV_SYNC_CONN_COMPLETE:
2418 case HCI_EV_DISCONN_COMPLETE:
2419 case HCI_EV_VENDOR_SPECIFIC:
2420 return 0;
2421 case HCI_EV_LE_META:
2422 /* Ignore frequent but not useful events that result in
2423 * costing too much space.
2424 */
2425 switch (buf[2]) {
2426 case HCI_EV_LE_CONN_COMPLETE:
2427 case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
2428 case HCI_EV_LE_CONN_UPDATE_COMPLETE:
2429 return 0;
2430 }
2431 return 1;
2432 case HCI_EV_CMD_COMPLETE:
2433 return cmd_cmplt_filter_out(buf);
2434 case HCI_EV_CMD_STATUS:
2435 return cmd_status_filter_out(buf);
2436 default:
2437 return 1;
2438 }
2439 }
2440
rtk_btcoex_evt_enqueue(__u8 * s,__u16 count)2441 static void rtk_btcoex_evt_enqueue(__u8 *s, __u16 count)
2442 {
2443 struct rtl_hci_ev *ev;
2444
2445 if (ev_filter_out(s))
2446 return;
2447
2448 ev = rtl_ev_node_get(&btrtl_coex);
2449 if (!ev) {
2450 RTKBT_ERR("%s: no free ev node.", __func__);
2451 return;
2452 }
2453
2454 if (count > MAX_LEN_OF_HCI_EV) {
2455 memcpy(ev->data, s, MAX_LEN_OF_HCI_EV);
2456 ev->len = MAX_LEN_OF_HCI_EV;
2457 } else {
2458 memcpy(ev->data, s, count);
2459 ev->len = count;
2460 }
2461
2462 rtl_ev_node_to_used(&btrtl_coex, ev);
2463
2464 queue_delayed_work(btrtl_coex.fw_wq, &btrtl_coex.fw_work, 0);
2465 }
2466
2467 /* Context: in_interrupt() */
rtk_btcoex_parse_event(uint8_t * buffer,int count)2468 void rtk_btcoex_parse_event(uint8_t *buffer, int count)
2469 {
2470 struct rtl_coex_struct *coex = &btrtl_coex;
2471 __u8 *tbuff;
2472 __u16 elen = 0;
2473
2474 /* RTKBT_DBG("%s: parse ev.", __func__); */
2475 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2476 /* RTKBT_INFO("%s: Coex is closed, ignore", __func__); */
2477 RTKBT_INFO("%s: Coex is closed, ignore %x, %x",
2478 __func__, buffer[0], buffer[1]);
2479 return;
2480 }
2481
2482 spin_lock(&coex->rxlock);
2483
2484 /* coex->tbuff will be set to NULL when initializing or
2485 * there is a complete frame or there is start of a frame */
2486 tbuff = coex->tbuff;
2487
2488 while (count) {
2489 int len;
2490
2491 /* Start of a frame */
2492 if (!tbuff) {
2493 tbuff = coex->back_buff;
2494 coex->tbuff = NULL;
2495 coex->elen = 0;
2496
2497 coex->pkt_type = HCI_EVENT_PKT;
2498 coex->expect = HCI_EVENT_HDR_SIZE;
2499 }
2500
2501 len = min_t(uint, coex->expect, count);
2502 memcpy(tbuff, buffer, len);
2503 tbuff += len;
2504 coex->elen += len;
2505
2506 count -= len;
2507 buffer += len;
2508 coex->expect -= len;
2509
2510 if (coex->elen == HCI_EVENT_HDR_SIZE) {
2511 /* Complete event header */
2512 coex->expect =
2513 ((struct hci_event_hdr *)coex->back_buff)->plen;
2514 if (coex->expect > HCI_MAX_EVENT_SIZE - coex->elen) {
2515 tbuff = NULL;
2516 coex->elen = 0;
2517 RTKBT_ERR("tbuff room is not enough");
2518 break;
2519 }
2520 }
2521
2522 if (coex->expect == 0) {
2523 /* Complete frame */
2524 elen = coex->elen;
2525 spin_unlock(&coex->rxlock);
2526 rtk_btcoex_evt_enqueue(coex->back_buff, elen);
2527 spin_lock(&coex->rxlock);
2528
2529 tbuff = NULL;
2530 coex->elen = 0;
2531 }
2532 }
2533
2534 /* coex->tbuff would be non-NULL if there isn't a complete frame
2535 * And it will be updated next time */
2536 coex->tbuff = tbuff;
2537 spin_unlock(&coex->rxlock);
2538 }
2539
2540
rtk_btcoex_parse_l2cap_data_tx(uint8_t * buffer,int count)2541 void rtk_btcoex_parse_l2cap_data_tx(uint8_t *buffer, int count)
2542 {
2543 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2544 RTKBT_INFO("%s: Coex is closed, ignore", __func__);
2545 return;
2546 }
2547
2548 rtl_l2_data_process(buffer, count, 1);
2549 //u16 handle, total_len, pdu_len, channel_ID, command_len, psm, scid,
2550 // dcid, result, status;
2551 //u8 flag, code, identifier;
2552 //u8 *pp = (u8 *) (skb->data);
2553 //STREAM_TO_UINT16(handle, pp);
2554 //flag = handle >> 12;
2555 //handle = handle & 0x0FFF;
2556 //STREAM_TO_UINT16(total_len, pp);
2557 //STREAM_TO_UINT16(pdu_len, pp);
2558 //STREAM_TO_UINT16(channel_ID, pp);
2559
2560 //if (channel_ID == 0x0001) {
2561 // code = *pp++;
2562 // switch (code) {
2563 // case L2CAP_CONN_REQ:
2564 // identifier = *pp++;
2565 // STREAM_TO_UINT16(command_len, pp);
2566 // STREAM_TO_UINT16(psm, pp);
2567 // STREAM_TO_UINT16(scid, pp);
2568 // RTKBT_DBG("TX l2cap conn req, hndl %x, PSM %x, scid=%x",
2569 // handle, psm, scid);
2570 // handle_l2cap_con_req(handle, psm, scid, 1);
2571 // break;
2572
2573 // case L2CAP_CONN_RSP:
2574 // identifier = *pp++;
2575 // STREAM_TO_UINT16(command_len, pp);
2576 // STREAM_TO_UINT16(dcid, pp);
2577 // STREAM_TO_UINT16(scid, pp);
2578 // STREAM_TO_UINT16(result, pp);
2579 // STREAM_TO_UINT16(status, pp);
2580 // RTKBT_DBG("TX l2cap conn rsp, hndl %x, dcid %x, "
2581 // "scid %x, result %x",
2582 // handle, dcid, scid, result);
2583 // handle_l2cap_con_rsp(handle, dcid, scid, 1, result);
2584 // break;
2585
2586 // case L2CAP_DISCONN_REQ:
2587 // identifier = *pp++;
2588 // STREAM_TO_UINT16(command_len, pp);
2589 // STREAM_TO_UINT16(dcid, pp);
2590 // STREAM_TO_UINT16(scid, pp);
2591 // RTKBT_DBG("TX l2cap disconn req, hndl %x, dcid %x, "
2592 // "scid %x", handle, dcid, scid);
2593 // handle_l2cap_discon_req(handle, dcid, scid, 1);
2594 // break;
2595
2596 // case L2CAP_DISCONN_RSP:
2597 // break;
2598
2599 // default:
2600 // break;
2601 // }
2602 //} else {
2603 // if ((flag != 0x01) && (is_profile_connected(profile_a2dp) || is_profile_connected(profile_pan))) //Do not count the continuous packets
2604 // packets_count(handle, channel_ID, pdu_len, 1, pp);
2605 //}
2606 }
2607
rtk_btcoex_parse_l2cap_data_rx(uint8_t * buffer,int count)2608 void rtk_btcoex_parse_l2cap_data_rx(uint8_t *buffer, int count)
2609 {
2610 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2611 RTKBT_INFO("%s: Coex is closed, ignore", __func__);
2612 return;
2613 }
2614
2615 rtl_l2_data_process(buffer, count, 0);
2616 //u16 handle, total_len, pdu_len, channel_ID, command_len, psm, scid,
2617 // dcid, result, status;
2618 //u8 flag, code, identifier;
2619 //u8 *pp = urb->transfer_buffer;
2620 //STREAM_TO_UINT16(handle, pp);
2621 //flag = handle >> 12;
2622 //handle = handle & 0x0FFF;
2623 //STREAM_TO_UINT16(total_len, pp);
2624 //STREAM_TO_UINT16(pdu_len, pp);
2625 //STREAM_TO_UINT16(channel_ID, pp);
2626
2627 //if (channel_ID == 0x0001) {
2628 // code = *pp++;
2629 // switch (code) {
2630 // case L2CAP_CONN_REQ:
2631 // identifier = *pp++;
2632 // STREAM_TO_UINT16(command_len, pp);
2633 // STREAM_TO_UINT16(psm, pp);
2634 // STREAM_TO_UINT16(scid, pp);
2635 // RTKBT_DBG("RX l2cap conn req, hndl %x, PSM %x, scid %x",
2636 // handle, psm, scid);
2637 // handle_l2cap_con_req(handle, psm, scid, 0);
2638 // break;
2639
2640 // case L2CAP_CONN_RSP:
2641 // identifier = *pp++;
2642 // STREAM_TO_UINT16(command_len, pp);
2643 // STREAM_TO_UINT16(dcid, pp);
2644 // STREAM_TO_UINT16(scid, pp);
2645 // STREAM_TO_UINT16(result, pp);
2646 // STREAM_TO_UINT16(status, pp);
2647 // RTKBT_DBG("RX l2cap conn rsp, hndl %x, dcid %x, "
2648 // "scid %x, result %x",
2649 // handle, dcid, scid, result);
2650 // handle_l2cap_con_rsp(handle, dcid, scid, 0, result);
2651 // break;
2652
2653 // case L2CAP_DISCONN_REQ:
2654 // identifier = *pp++;
2655 // STREAM_TO_UINT16(command_len, pp);
2656 // STREAM_TO_UINT16(dcid, pp);
2657 // STREAM_TO_UINT16(scid, pp);
2658 // RTKBT_DBG("RX l2cap disconn req, hndl %x, dcid %x, "
2659 // "scid %x", handle, dcid, scid);
2660 // handle_l2cap_discon_req(handle, dcid, scid, 0);
2661 // break;
2662
2663 // case L2CAP_DISCONN_RSP:
2664 // break;
2665
2666 // default:
2667 // break;
2668 // }
2669 //} else {
2670 // if ((flag != 0x01) && (is_profile_connected(profile_a2dp) || is_profile_connected(profile_pan))) //Do not count the continuous packets
2671 // packets_count(handle, channel_ID, pdu_len, 0, pp);
2672 //}
2673 }
2674
2675 #ifdef RTB_SOFTWARE_MAILBOX
2676
2677 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
polling_bt_info(struct timer_list * unused)2678 static void polling_bt_info(struct timer_list *unused)
2679 #else
2680 static void polling_bt_info(unsigned long data)
2681 #endif
2682 {
2683 uint8_t temp_cmd[1];
2684 RTKBT_DBG("polling timer");
2685 if (btrtl_coex.polling_enable) {
2686 //temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO;
2687 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_STATUS_INFO;
2688 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 1, temp_cmd);
2689 }
2690 mod_timer(&btrtl_coex.polling_timer,
2691 jiffies + msecs_to_jiffies(1000 * btrtl_coex.polling_interval));
2692 }
2693
rtk_handle_bt_info_control(uint8_t * p)2694 static void rtk_handle_bt_info_control(uint8_t *p)
2695 {
2696 uint8_t temp_cmd[20];
2697 struct rtl_btinfo_ctl *ctl = (struct rtl_btinfo_ctl*)p;
2698 RTKBT_DBG("Received polling_enable %u, polling_time %u, "
2699 "autoreport_enable %u", ctl->polling_enable,
2700 ctl->polling_time, ctl->autoreport_enable);
2701 RTKBT_DBG("coex: original polling_enable %u",
2702 btrtl_coex.polling_enable);
2703
2704 if (ctl->polling_enable && !btrtl_coex.polling_enable) {
2705 /* setup polling timer for getting bt info from firmware */
2706 btrtl_coex.polling_timer.expires =
2707 jiffies + msecs_to_jiffies(ctl->polling_time * 1000);
2708 mod_timer(&btrtl_coex.polling_timer,
2709 btrtl_coex.polling_timer.expires);
2710 }
2711
2712 /* Close bt info polling timer */
2713 if (!ctl->polling_enable && btrtl_coex.polling_enable)
2714 del_timer(&btrtl_coex.polling_timer);
2715
2716 if (btrtl_coex.autoreport != ctl->autoreport_enable) {
2717 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE;
2718 temp_cmd[1] = 1;
2719 temp_cmd[2] = ctl->autoreport_enable;
2720 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2721 }
2722
2723 btrtl_coex.polling_enable = ctl->polling_enable;
2724 btrtl_coex.polling_interval = ctl->polling_time;
2725 btrtl_coex.autoreport = ctl->autoreport_enable;
2726
2727 rtk_notify_info_to_wifi(HOST_RESPONSE, 0, NULL);
2728 }
2729
rtk_handle_bt_coex_control(uint8_t * p)2730 static void rtk_handle_bt_coex_control(uint8_t * p)
2731 {
2732 uint8_t temp_cmd[20];
2733 uint8_t opcode, opcode_len, value, power_decrease, psd_mode,
2734 access_type;
2735
2736 opcode = *p++;
2737 RTKBT_DBG("receive bt coex control event from wifi, op 0x%02x", opcode);
2738
2739 switch (opcode) {
2740 case BT_PATCH_VERSION_QUERY:
2741 rtk_notify_btpatch_version_to_wifi();
2742 break;
2743
2744 case IGNORE_WLAN_ACTIVE_CONTROL:
2745 opcode_len = *p++;
2746 value = *p++;
2747 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD;
2748 temp_cmd[1] = 1;
2749 temp_cmd[2] = value;
2750 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2751 break;
2752
2753 case LNA_CONSTRAIN_CONTROL:
2754 opcode_len = *p++;
2755 value = *p++;
2756 temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT;
2757 temp_cmd[1] = 1;
2758 temp_cmd[2] = value;
2759 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2760 break;
2761
2762 case BT_POWER_DECREASE_CONTROL:
2763 opcode_len = *p++;
2764 power_decrease = *p++;
2765 temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD;
2766 temp_cmd[1] = 1;
2767 temp_cmd[2] = power_decrease;
2768 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2769 break;
2770
2771 case BT_PSD_MODE_CONTROL:
2772 opcode_len = *p++;
2773 psd_mode = *p++;
2774 temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE;
2775 temp_cmd[1] = 1;
2776 temp_cmd[2] = psd_mode;
2777 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2778 break;
2779
2780 case WIFI_BW_CHNL_NOTIFY:
2781 opcode_len = *p++;
2782 temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD;
2783 temp_cmd[1] = 3;
2784 memcpy(temp_cmd + 2, p, 3); //wifi_state, wifi_centralchannel, chnnels_btnotuse
2785 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 5, temp_cmd);
2786 break;
2787
2788 case QUERY_BT_AFH_MAP:
2789 opcode_len = *p++;
2790 btrtl_coex.piconet_id = *p++;
2791 btrtl_coex.mode = *p++;
2792 temp_cmd[0] = HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L;
2793 temp_cmd[1] = 2;
2794 temp_cmd[2] = btrtl_coex.piconet_id;
2795 temp_cmd[3] = btrtl_coex.mode;
2796 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd);
2797 break;
2798
2799 case BT_REGISTER_ACCESS:
2800 opcode_len = *p++;
2801 access_type = *p++;
2802 if (access_type == 0) { //read
2803 temp_cmd[0] = HCI_VENDOR_SUB_CMD_RD_REG_REQ;
2804 temp_cmd[1] = 5;
2805 temp_cmd[2] = *p++;
2806 memcpy(temp_cmd + 3, p, 4);
2807 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 7,
2808 temp_cmd);
2809 } else { //write
2810 temp_cmd[0] = HCI_VENDOR_SUB_CMD_RD_REG_REQ;
2811 temp_cmd[1] = 5;
2812 temp_cmd[2] = *p++;
2813 memcpy(temp_cmd + 3, p, 8);
2814 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 11,
2815 temp_cmd);
2816 }
2817 break;
2818
2819 default:
2820 break;
2821 }
2822 }
2823
rtk_handle_event_from_wifi(uint8_t * msg)2824 static void rtk_handle_event_from_wifi(uint8_t * msg)
2825 {
2826 uint8_t *p = msg;
2827 uint8_t event_code = *p++;
2828 uint8_t total_length;
2829 uint8_t extension_event;
2830 uint8_t operation;
2831 uint16_t wifi_opcode;
2832 uint8_t op_status;
2833
2834 if (memcmp(msg, invite_rsp, sizeof(invite_rsp)) == 0) {
2835 RTKBT_DBG("receive invite rsp from wifi, wifi is already on");
2836 btrtl_coex.wifi_on = 1;
2837 rtk_notify_extension_version_to_wifi();
2838 }
2839
2840 if (memcmp(msg, attend_req, sizeof(attend_req)) == 0) {
2841 RTKBT_DBG("receive attend req from wifi, wifi turn on");
2842 btrtl_coex.wifi_on = 1;
2843 rtkbt_coexmsg_send(attend_ack, sizeof(attend_ack));
2844 rtk_notify_extension_version_to_wifi();
2845 }
2846
2847 if (memcmp(msg, wifi_leave, sizeof(wifi_leave)) == 0) {
2848 RTKBT_DBG("receive wifi leave from wifi, wifi turn off");
2849 btrtl_coex.wifi_on = 0;
2850 rtkbt_coexmsg_send(leave_ack, sizeof(leave_ack));
2851 if (btrtl_coex.polling_enable) {
2852 btrtl_coex.polling_enable = 0;
2853 del_timer(&btrtl_coex.polling_timer);
2854 }
2855 }
2856
2857 if (memcmp(msg, leave_ack, sizeof(leave_ack)) == 0) {
2858 RTKBT_DBG("receive leave ack from wifi");
2859 }
2860
2861 if (event_code == 0xFE) {
2862 total_length = *p++;
2863 extension_event = *p++;
2864 switch (extension_event) {
2865 case RTK_HS_EXTENSION_EVENT_WIFI_SCAN:
2866 operation = *p;
2867 RTKBT_DBG("Recv WiFi scan notify event from WiFi, "
2868 "op 0x%02x", operation);
2869 break;
2870
2871 case RTK_HS_EXTENSION_EVENT_HCI_BT_INFO_CONTROL:
2872 rtk_handle_bt_info_control(p);
2873 break;
2874
2875 case RTK_HS_EXTENSION_EVENT_HCI_BT_COEX_CONTROL:
2876 rtk_handle_bt_coex_control(p);
2877 break;
2878
2879 default:
2880 break;
2881 }
2882 }
2883
2884 if (event_code == 0x0E) {
2885 p += 2; //length, number of complete packets
2886 STREAM_TO_UINT16(wifi_opcode, p);
2887 op_status = *p;
2888 RTKBT_DBG("Recv cmd complete event from WiFi, op 0x%02x, "
2889 "status 0x%02x", wifi_opcode, op_status);
2890 }
2891 }
2892 #endif /* RTB_SOFTWARE_MAILBOX */
2893
rtl_free_frags(struct rtl_coex_struct * coex)2894 static inline void rtl_free_frags(struct rtl_coex_struct *coex)
2895 {
2896 unsigned long flags;
2897
2898 spin_lock_irqsave(&coex->rxlock, flags);
2899
2900 coex->elen = 0;
2901 coex->tbuff = NULL;
2902
2903 spin_unlock_irqrestore(&coex->rxlock, flags);
2904 }
2905
rtk_btcoex_open(struct hci_dev * hdev)2906 void rtk_btcoex_open(struct hci_dev *hdev)
2907 {
2908 if (test_and_set_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2909 RTKBT_WARN("RTL COEX is already running.");
2910 return;
2911 }
2912
2913 RTKBT_INFO("Open BTCOEX");
2914
2915 /* Just for test */
2916 //struct rtl_btinfo_ctl ctl;
2917
2918 INIT_DELAYED_WORK(&btrtl_coex.fw_work, (void *)rtl_ev_work);
2919 #ifdef RTB_SOFTWARE_MAILBOX
2920 #ifdef RTK_COEX_OVER_SYMBOL
2921 INIT_WORK(&rtw_work, rtw_work_func);
2922 skb_queue_head_init(&rtw_q);
2923 rtw_coex_on = 1;
2924 #else
2925 INIT_DELAYED_WORK(&btrtl_coex.sock_work,
2926 (void *)udpsocket_recv_data);
2927 #endif
2928 #endif /* RTB_SOFTWARE_MAILBOX */
2929 INIT_DELAYED_WORK(&btrtl_coex.l2_work, (void *)rtl_l2_work);
2930
2931 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
2932 #ifdef RTB_SOFTWARE_MAILBOX
2933 timer_setup(&btrtl_coex.polling_timer, polling_bt_info, 0);
2934 #endif
2935 timer_setup(&btrtl_coex.a2dp_count_timer, count_a2dp_packet_timeout, 0);
2936 timer_setup(&btrtl_coex.pan_count_timer, count_pan_packet_timeout, 0);
2937 timer_setup(&btrtl_coex.hogp_count_timer, count_hogp_packet_timeout, 0);
2938 #else
2939 #ifdef RTB_SOFTWARE_MAILBOX
2940 setup_timer(&btrtl_coex.polling_timer, polling_bt_info, 0);
2941 #endif
2942 setup_timer(&btrtl_coex.a2dp_count_timer, count_a2dp_packet_timeout, 0);
2943 setup_timer(&btrtl_coex.pan_count_timer, count_pan_packet_timeout, 0);
2944 setup_timer(&btrtl_coex.hogp_count_timer, count_hogp_packet_timeout, 0);
2945 #endif
2946
2947 btrtl_coex.hdev = hdev;
2948 #ifdef RTB_SOFTWARE_MAILBOX
2949 btrtl_coex.wifi_on = 0;
2950 #endif
2951
2952 init_profile_hash(&btrtl_coex);
2953 init_connection_hash(&btrtl_coex);
2954
2955 btrtl_coex.pkt_type = 0;
2956 btrtl_coex.expect = 0;
2957 btrtl_coex.elen = 0;
2958 btrtl_coex.tbuff = NULL;
2959
2960 #ifdef RTB_SOFTWARE_MAILBOX
2961 #ifndef RTK_COEX_OVER_SYMBOL
2962 create_udpsocket();
2963 #endif
2964 rtkbt_coexmsg_send(invite_req, sizeof(invite_req));
2965 #endif
2966
2967 /* Just for test */
2968 //ctl.polling_enable = 1;
2969 //ctl.polling_time = 1;
2970 //ctl.autoreport_enable = 1;
2971 //rtk_handle_bt_info_control((u8 *)&ctl);
2972 }
2973
rtk_btcoex_close(void)2974 void rtk_btcoex_close(void)
2975 {
2976 int kk = 0;
2977
2978 if (!test_and_clear_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2979 RTKBT_WARN("RTL COEX is already closed.");
2980 return;
2981 }
2982
2983 RTKBT_INFO("Close BTCOEX");
2984
2985 #ifdef RTB_SOFTWARE_MAILBOX
2986 /* Close coex socket */
2987 if (btrtl_coex.wifi_on)
2988 rtkbt_coexmsg_send(bt_leave, sizeof(bt_leave));
2989 #ifdef RTK_COEX_OVER_SYMBOL
2990 rtw_coex_on = 0;
2991 skb_queue_purge(&rtw_q);
2992 cancel_work_sync(&rtw_work);
2993 #else
2994 cancel_delayed_work_sync(&btrtl_coex.sock_work);
2995 if (btrtl_coex.sock_open) {
2996 btrtl_coex.sock_open = 0;
2997 RTKBT_DBG("release udp socket");
2998 sock_release(btrtl_coex.udpsock);
2999 }
3000 #endif
3001
3002 /* Delete all timers */
3003 if (btrtl_coex.polling_enable) {
3004 btrtl_coex.polling_enable = 0;
3005 del_timer_sync(&(btrtl_coex.polling_timer));
3006 }
3007 #endif /* RTB_SOFTWARE_MAILBOX */
3008
3009 del_timer_sync(&btrtl_coex.a2dp_count_timer);
3010 del_timer_sync(&btrtl_coex.pan_count_timer);
3011 del_timer_sync(&btrtl_coex.hogp_count_timer);
3012
3013 cancel_delayed_work_sync(&btrtl_coex.fw_work);
3014 cancel_delayed_work_sync(&btrtl_coex.l2_work);
3015
3016 flush_connection_hash(&btrtl_coex);
3017 flush_profile_hash(&btrtl_coex);
3018 btrtl_coex.profile_bitmap = 0;
3019 btrtl_coex.profile_status = 0;
3020 for (kk = 0; kk < 8; kk++)
3021 btrtl_coex.profile_refcount[kk] = 0;
3022
3023 rtl_free_frags(&btrtl_coex);
3024 RTKBT_DBG("-x");
3025 }
3026
rtk_btcoex_probe(struct hci_dev * hdev)3027 void rtk_btcoex_probe(struct hci_dev *hdev)
3028 {
3029 btrtl_coex.hdev = hdev;
3030 spin_lock_init(&btrtl_coex.spin_lock_sock);
3031 spin_lock_init(&btrtl_coex.spin_lock_profile);
3032 }
3033
rtk_btcoex_init(void)3034 void rtk_btcoex_init(void)
3035 {
3036 RTKBT_DBG("%s: version: %s", __func__, RTK_VERSION);
3037 RTKBT_DBG("create workqueue");
3038 #ifdef RTB_SOFTWARE_MAILBOX
3039 #ifdef RTK_COEX_OVER_SYMBOL
3040 RTKBT_INFO("Coex over Symbol");
3041 rtw_wq = create_workqueue("btcoexwork");
3042 skb_queue_head_init(&rtw_q);
3043 #else
3044 RTKBT_INFO("Coex over UDP");
3045 btrtl_coex.sock_wq = create_workqueue("btudpwork");
3046 #endif
3047 #endif /* RTB_SOFTWARE_MAILBOX */
3048 btrtl_coex.fw_wq = create_workqueue("btfwwork");
3049 rtl_alloc_buff(&btrtl_coex);
3050 spin_lock_init(&btrtl_coex.rxlock);
3051 }
3052
rtk_btcoex_exit(void)3053 void rtk_btcoex_exit(void)
3054 {
3055 RTKBT_DBG("%s: destroy workqueue", __func__);
3056 #ifdef RTB_SOFTWARE_MAILBOX
3057 #ifdef RTK_COEX_OVER_SYMBOL
3058 flush_workqueue(rtw_wq);
3059 destroy_workqueue(rtw_wq);
3060 #else
3061 flush_workqueue(btrtl_coex.sock_wq);
3062 destroy_workqueue(btrtl_coex.sock_wq);
3063 #endif
3064 #endif
3065 flush_workqueue(btrtl_coex.fw_wq);
3066 destroy_workqueue(btrtl_coex.fw_wq);
3067 rtl_free_buff(&btrtl_coex);
3068 }
3069