xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bluetooth_uart_driver/rtk_coex.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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