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
ev_filter_out(u8 * buf)2376 int ev_filter_out(u8 *buf)
2377 {
2378 switch (buf[0]) {
2379 case HCI_EV_INQUIRY_COMPLETE:
2380 case HCI_EV_PIN_CODE_REQ:
2381 case HCI_EV_IO_CAPA_REQUEST:
2382 case HCI_EV_AUTH_COMPLETE:
2383 case HCI_EV_LINK_KEY_NOTIFY:
2384 case HCI_EV_MODE_CHANGE:
2385 case HCI_EV_CMD_COMPLETE:
2386 case HCI_EV_CMD_STATUS:
2387 case HCI_EV_CONN_COMPLETE:
2388 case HCI_EV_SYNC_CONN_COMPLETE:
2389 case HCI_EV_DISCONN_COMPLETE:
2390 case HCI_EV_VENDOR_SPECIFIC:
2391 return 0;
2392 case HCI_EV_LE_META:
2393 /* Ignore frequent but not useful events that result in
2394 * costing too much space.
2395 */
2396 switch (buf[2]) {
2397 case HCI_EV_LE_CONN_COMPLETE:
2398 case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
2399 case HCI_EV_LE_CONN_UPDATE_COMPLETE:
2400 return 0;
2401 }
2402 return 1;
2403 default:
2404 return 1;
2405 }
2406 }
2407
rtk_btcoex_evt_enqueue(__u8 * s,__u16 count)2408 static void rtk_btcoex_evt_enqueue(__u8 *s, __u16 count)
2409 {
2410 struct rtl_hci_ev *ev;
2411
2412 if (ev_filter_out(s))
2413 return;
2414
2415 ev = rtl_ev_node_get(&btrtl_coex);
2416 if (!ev) {
2417 RTKBT_ERR("%s: no free ev node.", __func__);
2418 return;
2419 }
2420
2421 if (count > MAX_LEN_OF_HCI_EV) {
2422 memcpy(ev->data, s, MAX_LEN_OF_HCI_EV);
2423 ev->len = MAX_LEN_OF_HCI_EV;
2424 } else {
2425 memcpy(ev->data, s, count);
2426 ev->len = count;
2427 }
2428
2429 rtl_ev_node_to_used(&btrtl_coex, ev);
2430
2431 queue_delayed_work(btrtl_coex.fw_wq, &btrtl_coex.fw_work, 0);
2432 }
2433
2434 /* Context: in_interrupt() */
rtk_btcoex_parse_event(uint8_t * buffer,int count)2435 void rtk_btcoex_parse_event(uint8_t *buffer, int count)
2436 {
2437 struct rtl_coex_struct *coex = &btrtl_coex;
2438 __u8 *tbuff;
2439 __u16 elen = 0;
2440
2441 /* RTKBT_DBG("%s: parse ev.", __func__); */
2442 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2443 /* RTKBT_INFO("%s: Coex is closed, ignore", __func__); */
2444 RTKBT_INFO("%s: Coex is closed, ignore %x, %x",
2445 __func__, buffer[0], buffer[1]);
2446 return;
2447 }
2448
2449 spin_lock(&coex->rxlock);
2450
2451 /* coex->tbuff will be set to NULL when initializing or
2452 * there is a complete frame or there is start of a frame */
2453 tbuff = coex->tbuff;
2454
2455 while (count) {
2456 int len;
2457
2458 /* Start of a frame */
2459 if (!tbuff) {
2460 tbuff = coex->back_buff;
2461 coex->tbuff = NULL;
2462 coex->elen = 0;
2463
2464 coex->pkt_type = HCI_EVENT_PKT;
2465 coex->expect = HCI_EVENT_HDR_SIZE;
2466 }
2467
2468 len = min_t(uint, coex->expect, count);
2469 memcpy(tbuff, buffer, len);
2470 tbuff += len;
2471 coex->elen += len;
2472
2473 count -= len;
2474 buffer += len;
2475 coex->expect -= len;
2476
2477 if (coex->elen == HCI_EVENT_HDR_SIZE) {
2478 /* Complete event header */
2479 coex->expect =
2480 ((struct hci_event_hdr *)coex->back_buff)->plen;
2481 if (coex->expect > HCI_MAX_EVENT_SIZE - coex->elen) {
2482 tbuff = NULL;
2483 coex->elen = 0;
2484 RTKBT_ERR("tbuff room is not enough");
2485 break;
2486 }
2487 }
2488
2489 if (coex->expect == 0) {
2490 /* Complete frame */
2491 elen = coex->elen;
2492 spin_unlock(&coex->rxlock);
2493 rtk_btcoex_evt_enqueue(coex->back_buff, elen);
2494 spin_lock(&coex->rxlock);
2495
2496 tbuff = NULL;
2497 coex->elen = 0;
2498 }
2499 }
2500
2501 /* coex->tbuff would be non-NULL if there isn't a complete frame
2502 * And it will be updated next time */
2503 coex->tbuff = tbuff;
2504 spin_unlock(&coex->rxlock);
2505 }
2506
2507
rtk_btcoex_parse_l2cap_data_tx(uint8_t * buffer,int count)2508 void rtk_btcoex_parse_l2cap_data_tx(uint8_t *buffer, int count)
2509 {
2510 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2511 RTKBT_INFO("%s: Coex is closed, ignore", __func__);
2512 return;
2513 }
2514
2515 rtl_l2_data_process(buffer, count, 1);
2516 //u16 handle, total_len, pdu_len, channel_ID, command_len, psm, scid,
2517 // dcid, result, status;
2518 //u8 flag, code, identifier;
2519 //u8 *pp = (u8 *) (skb->data);
2520 //STREAM_TO_UINT16(handle, pp);
2521 //flag = handle >> 12;
2522 //handle = handle & 0x0FFF;
2523 //STREAM_TO_UINT16(total_len, pp);
2524 //STREAM_TO_UINT16(pdu_len, pp);
2525 //STREAM_TO_UINT16(channel_ID, pp);
2526
2527 //if (channel_ID == 0x0001) {
2528 // code = *pp++;
2529 // switch (code) {
2530 // case L2CAP_CONN_REQ:
2531 // identifier = *pp++;
2532 // STREAM_TO_UINT16(command_len, pp);
2533 // STREAM_TO_UINT16(psm, pp);
2534 // STREAM_TO_UINT16(scid, pp);
2535 // RTKBT_DBG("TX l2cap conn req, hndl %x, PSM %x, scid=%x",
2536 // handle, psm, scid);
2537 // handle_l2cap_con_req(handle, psm, scid, 1);
2538 // break;
2539
2540 // case L2CAP_CONN_RSP:
2541 // identifier = *pp++;
2542 // STREAM_TO_UINT16(command_len, pp);
2543 // STREAM_TO_UINT16(dcid, pp);
2544 // STREAM_TO_UINT16(scid, pp);
2545 // STREAM_TO_UINT16(result, pp);
2546 // STREAM_TO_UINT16(status, pp);
2547 // RTKBT_DBG("TX l2cap conn rsp, hndl %x, dcid %x, "
2548 // "scid %x, result %x",
2549 // handle, dcid, scid, result);
2550 // handle_l2cap_con_rsp(handle, dcid, scid, 1, result);
2551 // break;
2552
2553 // case L2CAP_DISCONN_REQ:
2554 // identifier = *pp++;
2555 // STREAM_TO_UINT16(command_len, pp);
2556 // STREAM_TO_UINT16(dcid, pp);
2557 // STREAM_TO_UINT16(scid, pp);
2558 // RTKBT_DBG("TX l2cap disconn req, hndl %x, dcid %x, "
2559 // "scid %x", handle, dcid, scid);
2560 // handle_l2cap_discon_req(handle, dcid, scid, 1);
2561 // break;
2562
2563 // case L2CAP_DISCONN_RSP:
2564 // break;
2565
2566 // default:
2567 // break;
2568 // }
2569 //} else {
2570 // if ((flag != 0x01) && (is_profile_connected(profile_a2dp) || is_profile_connected(profile_pan))) //Do not count the continuous packets
2571 // packets_count(handle, channel_ID, pdu_len, 1, pp);
2572 //}
2573 }
2574
rtk_btcoex_parse_l2cap_data_rx(uint8_t * buffer,int count)2575 void rtk_btcoex_parse_l2cap_data_rx(uint8_t *buffer, int count)
2576 {
2577 if (!test_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2578 RTKBT_INFO("%s: Coex is closed, ignore", __func__);
2579 return;
2580 }
2581
2582 rtl_l2_data_process(buffer, count, 0);
2583 //u16 handle, total_len, pdu_len, channel_ID, command_len, psm, scid,
2584 // dcid, result, status;
2585 //u8 flag, code, identifier;
2586 //u8 *pp = urb->transfer_buffer;
2587 //STREAM_TO_UINT16(handle, pp);
2588 //flag = handle >> 12;
2589 //handle = handle & 0x0FFF;
2590 //STREAM_TO_UINT16(total_len, pp);
2591 //STREAM_TO_UINT16(pdu_len, pp);
2592 //STREAM_TO_UINT16(channel_ID, pp);
2593
2594 //if (channel_ID == 0x0001) {
2595 // code = *pp++;
2596 // switch (code) {
2597 // case L2CAP_CONN_REQ:
2598 // identifier = *pp++;
2599 // STREAM_TO_UINT16(command_len, pp);
2600 // STREAM_TO_UINT16(psm, pp);
2601 // STREAM_TO_UINT16(scid, pp);
2602 // RTKBT_DBG("RX l2cap conn req, hndl %x, PSM %x, scid %x",
2603 // handle, psm, scid);
2604 // handle_l2cap_con_req(handle, psm, scid, 0);
2605 // break;
2606
2607 // case L2CAP_CONN_RSP:
2608 // identifier = *pp++;
2609 // STREAM_TO_UINT16(command_len, pp);
2610 // STREAM_TO_UINT16(dcid, pp);
2611 // STREAM_TO_UINT16(scid, pp);
2612 // STREAM_TO_UINT16(result, pp);
2613 // STREAM_TO_UINT16(status, pp);
2614 // RTKBT_DBG("RX l2cap conn rsp, hndl %x, dcid %x, "
2615 // "scid %x, result %x",
2616 // handle, dcid, scid, result);
2617 // handle_l2cap_con_rsp(handle, dcid, scid, 0, result);
2618 // break;
2619
2620 // case L2CAP_DISCONN_REQ:
2621 // identifier = *pp++;
2622 // STREAM_TO_UINT16(command_len, pp);
2623 // STREAM_TO_UINT16(dcid, pp);
2624 // STREAM_TO_UINT16(scid, pp);
2625 // RTKBT_DBG("RX l2cap disconn req, hndl %x, dcid %x, "
2626 // "scid %x", handle, dcid, scid);
2627 // handle_l2cap_discon_req(handle, dcid, scid, 0);
2628 // break;
2629
2630 // case L2CAP_DISCONN_RSP:
2631 // break;
2632
2633 // default:
2634 // break;
2635 // }
2636 //} else {
2637 // if ((flag != 0x01) && (is_profile_connected(profile_a2dp) || is_profile_connected(profile_pan))) //Do not count the continuous packets
2638 // packets_count(handle, channel_ID, pdu_len, 0, pp);
2639 //}
2640 }
2641
2642 #ifdef RTB_SOFTWARE_MAILBOX
2643
2644 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
polling_bt_info(struct timer_list * unused)2645 static void polling_bt_info(struct timer_list *unused)
2646 #else
2647 static void polling_bt_info(unsigned long data)
2648 #endif
2649 {
2650 uint8_t temp_cmd[1];
2651 RTKBT_DBG("polling timer");
2652 if (btrtl_coex.polling_enable) {
2653 //temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_REPORT_CONN_SCO_INQ_INFO;
2654 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_STATUS_INFO;
2655 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 1, temp_cmd);
2656 }
2657 mod_timer(&btrtl_coex.polling_timer,
2658 jiffies + msecs_to_jiffies(1000 * btrtl_coex.polling_interval));
2659 }
2660
rtk_handle_bt_info_control(uint8_t * p)2661 static void rtk_handle_bt_info_control(uint8_t *p)
2662 {
2663 uint8_t temp_cmd[20];
2664 struct rtl_btinfo_ctl *ctl = (struct rtl_btinfo_ctl*)p;
2665 RTKBT_DBG("Received polling_enable %u, polling_time %u, "
2666 "autoreport_enable %u", ctl->polling_enable,
2667 ctl->polling_time, ctl->autoreport_enable);
2668 RTKBT_DBG("coex: original polling_enable %u",
2669 btrtl_coex.polling_enable);
2670
2671 if (ctl->polling_enable && !btrtl_coex.polling_enable) {
2672 /* setup polling timer for getting bt info from firmware */
2673 btrtl_coex.polling_timer.expires =
2674 jiffies + msecs_to_jiffies(ctl->polling_time * 1000);
2675 mod_timer(&btrtl_coex.polling_timer,
2676 btrtl_coex.polling_timer.expires);
2677 }
2678
2679 /* Close bt info polling timer */
2680 if (!ctl->polling_enable && btrtl_coex.polling_enable)
2681 del_timer(&btrtl_coex.polling_timer);
2682
2683 if (btrtl_coex.autoreport != ctl->autoreport_enable) {
2684 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_AUTO_REPORT_ENABLE;
2685 temp_cmd[1] = 1;
2686 temp_cmd[2] = ctl->autoreport_enable;
2687 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2688 }
2689
2690 btrtl_coex.polling_enable = ctl->polling_enable;
2691 btrtl_coex.polling_interval = ctl->polling_time;
2692 btrtl_coex.autoreport = ctl->autoreport_enable;
2693
2694 rtk_notify_info_to_wifi(HOST_RESPONSE, 0, NULL);
2695 }
2696
rtk_handle_bt_coex_control(uint8_t * p)2697 static void rtk_handle_bt_coex_control(uint8_t * p)
2698 {
2699 uint8_t temp_cmd[20];
2700 uint8_t opcode, opcode_len, value, power_decrease, psd_mode,
2701 access_type;
2702
2703 opcode = *p++;
2704 RTKBT_DBG("receive bt coex control event from wifi, op 0x%02x", opcode);
2705
2706 switch (opcode) {
2707 case BT_PATCH_VERSION_QUERY:
2708 rtk_notify_btpatch_version_to_wifi();
2709 break;
2710
2711 case IGNORE_WLAN_ACTIVE_CONTROL:
2712 opcode_len = *p++;
2713 value = *p++;
2714 temp_cmd[0] = HCI_VENDOR_SUB_CMD_BT_ENABLE_IGNORE_WLAN_ACT_CMD;
2715 temp_cmd[1] = 1;
2716 temp_cmd[2] = value;
2717 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2718 break;
2719
2720 case LNA_CONSTRAIN_CONTROL:
2721 opcode_len = *p++;
2722 value = *p++;
2723 temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_LNA_CONSTRAINT;
2724 temp_cmd[1] = 1;
2725 temp_cmd[2] = value;
2726 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2727 break;
2728
2729 case BT_POWER_DECREASE_CONTROL:
2730 opcode_len = *p++;
2731 power_decrease = *p++;
2732 temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_FORCE_TX_POWER_CMD;
2733 temp_cmd[1] = 1;
2734 temp_cmd[2] = power_decrease;
2735 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2736 break;
2737
2738 case BT_PSD_MODE_CONTROL:
2739 opcode_len = *p++;
2740 psd_mode = *p++;
2741 temp_cmd[0] = HCI_VENDOR_SUB_CMD_SET_BT_PSD_MODE;
2742 temp_cmd[1] = 1;
2743 temp_cmd[2] = psd_mode;
2744 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 3, temp_cmd);
2745 break;
2746
2747 case WIFI_BW_CHNL_NOTIFY:
2748 opcode_len = *p++;
2749 temp_cmd[0] = HCI_VENDOR_SUB_CMD_WIFI_CHANNEL_AND_BANDWIDTH_CMD;
2750 temp_cmd[1] = 3;
2751 memcpy(temp_cmd + 2, p, 3); //wifi_state, wifi_centralchannel, chnnels_btnotuse
2752 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 5, temp_cmd);
2753 break;
2754
2755 case QUERY_BT_AFH_MAP:
2756 opcode_len = *p++;
2757 btrtl_coex.piconet_id = *p++;
2758 btrtl_coex.mode = *p++;
2759 temp_cmd[0] = HCI_VENDOR_SUB_CMD_GET_AFH_MAP_L;
2760 temp_cmd[1] = 2;
2761 temp_cmd[2] = btrtl_coex.piconet_id;
2762 temp_cmd[3] = btrtl_coex.mode;
2763 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 4, temp_cmd);
2764 break;
2765
2766 case BT_REGISTER_ACCESS:
2767 opcode_len = *p++;
2768 access_type = *p++;
2769 if (access_type == 0) { //read
2770 temp_cmd[0] = HCI_VENDOR_SUB_CMD_RD_REG_REQ;
2771 temp_cmd[1] = 5;
2772 temp_cmd[2] = *p++;
2773 memcpy(temp_cmd + 3, p, 4);
2774 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 7,
2775 temp_cmd);
2776 } else { //write
2777 temp_cmd[0] = HCI_VENDOR_SUB_CMD_RD_REG_REQ;
2778 temp_cmd[1] = 5;
2779 temp_cmd[2] = *p++;
2780 memcpy(temp_cmd + 3, p, 8);
2781 rtk_vendor_cmd_to_fw(HCI_VENDOR_MAILBOX_CMD, 11,
2782 temp_cmd);
2783 }
2784 break;
2785
2786 default:
2787 break;
2788 }
2789 }
2790
rtk_handle_event_from_wifi(uint8_t * msg)2791 static void rtk_handle_event_from_wifi(uint8_t * msg)
2792 {
2793 uint8_t *p = msg;
2794 uint8_t event_code = *p++;
2795 uint8_t total_length;
2796 uint8_t extension_event;
2797 uint8_t operation;
2798 uint16_t wifi_opcode;
2799 uint8_t op_status;
2800
2801 if (memcmp(msg, invite_rsp, sizeof(invite_rsp)) == 0) {
2802 RTKBT_DBG("receive invite rsp from wifi, wifi is already on");
2803 btrtl_coex.wifi_on = 1;
2804 rtk_notify_extension_version_to_wifi();
2805 }
2806
2807 if (memcmp(msg, attend_req, sizeof(attend_req)) == 0) {
2808 RTKBT_DBG("receive attend req from wifi, wifi turn on");
2809 btrtl_coex.wifi_on = 1;
2810 rtkbt_coexmsg_send(attend_ack, sizeof(attend_ack));
2811 rtk_notify_extension_version_to_wifi();
2812 }
2813
2814 if (memcmp(msg, wifi_leave, sizeof(wifi_leave)) == 0) {
2815 RTKBT_DBG("receive wifi leave from wifi, wifi turn off");
2816 btrtl_coex.wifi_on = 0;
2817 rtkbt_coexmsg_send(leave_ack, sizeof(leave_ack));
2818 if (btrtl_coex.polling_enable) {
2819 btrtl_coex.polling_enable = 0;
2820 del_timer(&btrtl_coex.polling_timer);
2821 }
2822 }
2823
2824 if (memcmp(msg, leave_ack, sizeof(leave_ack)) == 0) {
2825 RTKBT_DBG("receive leave ack from wifi");
2826 }
2827
2828 if (event_code == 0xFE) {
2829 total_length = *p++;
2830 extension_event = *p++;
2831 switch (extension_event) {
2832 case RTK_HS_EXTENSION_EVENT_WIFI_SCAN:
2833 operation = *p;
2834 RTKBT_DBG("Recv WiFi scan notify event from WiFi, "
2835 "op 0x%02x", operation);
2836 break;
2837
2838 case RTK_HS_EXTENSION_EVENT_HCI_BT_INFO_CONTROL:
2839 rtk_handle_bt_info_control(p);
2840 break;
2841
2842 case RTK_HS_EXTENSION_EVENT_HCI_BT_COEX_CONTROL:
2843 rtk_handle_bt_coex_control(p);
2844 break;
2845
2846 default:
2847 break;
2848 }
2849 }
2850
2851 if (event_code == 0x0E) {
2852 p += 2; //length, number of complete packets
2853 STREAM_TO_UINT16(wifi_opcode, p);
2854 op_status = *p;
2855 RTKBT_DBG("Recv cmd complete event from WiFi, op 0x%02x, "
2856 "status 0x%02x", wifi_opcode, op_status);
2857 }
2858 }
2859 #endif /* RTB_SOFTWARE_MAILBOX */
2860
rtl_free_frags(struct rtl_coex_struct * coex)2861 static inline void rtl_free_frags(struct rtl_coex_struct *coex)
2862 {
2863 unsigned long flags;
2864
2865 spin_lock_irqsave(&coex->rxlock, flags);
2866
2867 coex->elen = 0;
2868 coex->tbuff = NULL;
2869
2870 spin_unlock_irqrestore(&coex->rxlock, flags);
2871 }
2872
rtk_btcoex_open(struct hci_dev * hdev)2873 void rtk_btcoex_open(struct hci_dev *hdev)
2874 {
2875 if (test_and_set_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2876 RTKBT_WARN("RTL COEX is already running.");
2877 return;
2878 }
2879
2880 RTKBT_INFO("Open BTCOEX");
2881
2882 /* Just for test */
2883 //struct rtl_btinfo_ctl ctl;
2884
2885 INIT_DELAYED_WORK(&btrtl_coex.fw_work, (void *)rtl_ev_work);
2886 #ifdef RTB_SOFTWARE_MAILBOX
2887 #ifdef RTK_COEX_OVER_SYMBOL
2888 INIT_WORK(&rtw_work, rtw_work_func);
2889 skb_queue_head_init(&rtw_q);
2890 rtw_coex_on = 1;
2891 #else
2892 INIT_DELAYED_WORK(&btrtl_coex.sock_work,
2893 (void *)udpsocket_recv_data);
2894 #endif
2895 #endif /* RTB_SOFTWARE_MAILBOX */
2896 INIT_DELAYED_WORK(&btrtl_coex.l2_work, (void *)rtl_l2_work);
2897
2898 #if LINUX_VERSION_CODE > KERNEL_VERSION(4, 14, 0)
2899 #ifdef RTB_SOFTWARE_MAILBOX
2900 timer_setup(&btrtl_coex.polling_timer, polling_bt_info, 0);
2901 #endif
2902 timer_setup(&btrtl_coex.a2dp_count_timer, count_a2dp_packet_timeout, 0);
2903 timer_setup(&btrtl_coex.pan_count_timer, count_pan_packet_timeout, 0);
2904 timer_setup(&btrtl_coex.hogp_count_timer, count_hogp_packet_timeout, 0);
2905 #else
2906 #ifdef RTB_SOFTWARE_MAILBOX
2907 setup_timer(&btrtl_coex.polling_timer, polling_bt_info, 0);
2908 #endif
2909 setup_timer(&btrtl_coex.a2dp_count_timer, count_a2dp_packet_timeout, 0);
2910 setup_timer(&btrtl_coex.pan_count_timer, count_pan_packet_timeout, 0);
2911 setup_timer(&btrtl_coex.hogp_count_timer, count_hogp_packet_timeout, 0);
2912 #endif
2913
2914 btrtl_coex.hdev = hdev;
2915 #ifdef RTB_SOFTWARE_MAILBOX
2916 btrtl_coex.wifi_on = 0;
2917 #endif
2918
2919 init_profile_hash(&btrtl_coex);
2920 init_connection_hash(&btrtl_coex);
2921
2922 btrtl_coex.pkt_type = 0;
2923 btrtl_coex.expect = 0;
2924 btrtl_coex.elen = 0;
2925 btrtl_coex.tbuff = NULL;
2926
2927 #ifdef RTB_SOFTWARE_MAILBOX
2928 #ifndef RTK_COEX_OVER_SYMBOL
2929 create_udpsocket();
2930 #endif
2931 rtkbt_coexmsg_send(invite_req, sizeof(invite_req));
2932 #endif
2933
2934 /* Just for test */
2935 //ctl.polling_enable = 1;
2936 //ctl.polling_time = 1;
2937 //ctl.autoreport_enable = 1;
2938 //rtk_handle_bt_info_control((u8 *)&ctl);
2939 }
2940
rtk_btcoex_close(void)2941 void rtk_btcoex_close(void)
2942 {
2943 int kk = 0;
2944
2945 if (!test_and_clear_bit(RTL_COEX_RUNNING, &btrtl_coex.flags)) {
2946 RTKBT_WARN("RTL COEX is already closed.");
2947 return;
2948 }
2949
2950 RTKBT_INFO("Close BTCOEX");
2951
2952 #ifdef RTB_SOFTWARE_MAILBOX
2953 /* Close coex socket */
2954 if (btrtl_coex.wifi_on)
2955 rtkbt_coexmsg_send(bt_leave, sizeof(bt_leave));
2956 #ifdef RTK_COEX_OVER_SYMBOL
2957 rtw_coex_on = 0;
2958 skb_queue_purge(&rtw_q);
2959 cancel_work_sync(&rtw_work);
2960 #else
2961 cancel_delayed_work_sync(&btrtl_coex.sock_work);
2962 if (btrtl_coex.sock_open) {
2963 btrtl_coex.sock_open = 0;
2964 RTKBT_DBG("release udp socket");
2965 sock_release(btrtl_coex.udpsock);
2966 }
2967 #endif
2968
2969 /* Delete all timers */
2970 if (btrtl_coex.polling_enable) {
2971 btrtl_coex.polling_enable = 0;
2972 del_timer_sync(&(btrtl_coex.polling_timer));
2973 }
2974 #endif /* RTB_SOFTWARE_MAILBOX */
2975
2976 del_timer_sync(&btrtl_coex.a2dp_count_timer);
2977 del_timer_sync(&btrtl_coex.pan_count_timer);
2978 del_timer_sync(&btrtl_coex.hogp_count_timer);
2979
2980 cancel_delayed_work_sync(&btrtl_coex.fw_work);
2981 cancel_delayed_work_sync(&btrtl_coex.l2_work);
2982
2983 flush_connection_hash(&btrtl_coex);
2984 flush_profile_hash(&btrtl_coex);
2985 btrtl_coex.profile_bitmap = 0;
2986 btrtl_coex.profile_status = 0;
2987 for (kk = 0; kk < 8; kk++)
2988 btrtl_coex.profile_refcount[kk] = 0;
2989
2990 rtl_free_frags(&btrtl_coex);
2991 RTKBT_DBG("-x");
2992 }
2993
rtk_btcoex_probe(struct hci_dev * hdev)2994 void rtk_btcoex_probe(struct hci_dev *hdev)
2995 {
2996 btrtl_coex.hdev = hdev;
2997 spin_lock_init(&btrtl_coex.spin_lock_sock);
2998 spin_lock_init(&btrtl_coex.spin_lock_profile);
2999 }
3000
rtk_btcoex_init(void)3001 void rtk_btcoex_init(void)
3002 {
3003 RTKBT_DBG("%s: version: %s", __func__, RTK_VERSION);
3004 RTKBT_DBG("create workqueue");
3005 #ifdef RTB_SOFTWARE_MAILBOX
3006 #ifdef RTK_COEX_OVER_SYMBOL
3007 RTKBT_INFO("Coex over Symbol");
3008 rtw_wq = create_workqueue("btcoexwork");
3009 skb_queue_head_init(&rtw_q);
3010 #else
3011 RTKBT_INFO("Coex over UDP");
3012 btrtl_coex.sock_wq = create_workqueue("btudpwork");
3013 #endif
3014 #endif /* RTB_SOFTWARE_MAILBOX */
3015 btrtl_coex.fw_wq = create_workqueue("btfwwork");
3016 rtl_alloc_buff(&btrtl_coex);
3017 spin_lock_init(&btrtl_coex.rxlock);
3018 }
3019
rtk_btcoex_exit(void)3020 void rtk_btcoex_exit(void)
3021 {
3022 RTKBT_DBG("%s: destroy workqueue", __func__);
3023 #ifdef RTB_SOFTWARE_MAILBOX
3024 #ifdef RTK_COEX_OVER_SYMBOL
3025 flush_workqueue(rtw_wq);
3026 destroy_workqueue(rtw_wq);
3027 #else
3028 flush_workqueue(btrtl_coex.sock_wq);
3029 destroy_workqueue(btrtl_coex.sock_wq);
3030 #endif
3031 #endif
3032 flush_workqueue(btrtl_coex.fw_wq);
3033 destroy_workqueue(btrtl_coex.fw_wq);
3034 rtl_free_buff(&btrtl_coex);
3035 }
3036