Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nu11secur1ty
GitHub Repository: nu11secur1ty/Kali-Linux
Path: blob/master/ALFA-W1F1/RTL8814AU/hal/hal_hci/hal_usb.c
1307 views
1
/******************************************************************************
2
*
3
* Copyright(c) 2007 - 2017 Realtek Corporation.
4
*
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms of version 2 of the GNU General Public License as
7
* published by the Free Software Foundation.
8
*
9
* This program is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
* more details.
13
*
14
*****************************************************************************/
15
#define _HAL_USB_C_
16
17
#include <drv_types.h>
18
#include <hal_data.h>
19
20
int usb_init_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
21
{
22
struct recv_priv *precvpriv = &padapter->recvpriv;
23
int i, res = _SUCCESS;
24
struct recv_buf *precvbuf;
25
26
#ifdef PLATFORM_LINUX
27
tasklet_init(&precvpriv->recv_tasklet,
28
(void(*))usb_recv_tasklet,
29
(unsigned long)padapter);
30
#endif /* PLATFORM_LINUX */
31
32
#ifdef PLATFORM_FREEBSD
33
#ifdef CONFIG_RX_INDICATE_QUEUE
34
TASK_INIT(&precvpriv->rx_indicate_tasklet, 0, rtw_rx_indicate_tasklet, padapter);
35
#endif /* CONFIG_RX_INDICATE_QUEUE */
36
#endif /* PLATFORM_FREEBSD */
37
38
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
39
#ifdef PLATFORM_LINUX
40
precvpriv->int_in_urb = usb_alloc_urb(0, GFP_KERNEL);
41
if (precvpriv->int_in_urb == NULL) {
42
res = _FAIL;
43
RTW_INFO("alloc_urb for interrupt in endpoint fail !!!!\n");
44
goto exit;
45
}
46
#endif /* PLATFORM_LINUX */
47
precvpriv->int_in_buf = rtw_zmalloc(ini_in_buf_sz);
48
if (precvpriv->int_in_buf == NULL) {
49
res = _FAIL;
50
RTW_INFO("alloc_mem for interrupt in endpoint fail !!!!\n");
51
goto exit;
52
}
53
#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
54
55
/* init recv_buf */
56
_rtw_init_queue(&precvpriv->free_recv_buf_queue);
57
_rtw_init_queue(&precvpriv->recv_buf_pending_queue);
58
#ifndef CONFIG_USE_USB_BUFFER_ALLOC_RX
59
/* this is used only when RX_IOBUF is sk_buff */
60
skb_queue_head_init(&precvpriv->free_recv_skb_queue);
61
#endif
62
63
RTW_INFO("NR_RECVBUFF: %d\n", NR_RECVBUFF);
64
RTW_INFO("MAX_RECVBUF_SZ: %d\n", MAX_RECVBUF_SZ);
65
precvpriv->pallocated_recv_buf = rtw_zmalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4);
66
if (precvpriv->pallocated_recv_buf == NULL) {
67
res = _FAIL;
68
goto exit;
69
}
70
71
precvpriv->precv_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_recv_buf), 4);
72
73
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
74
75
for (i = 0; i < NR_RECVBUFF ; i++) {
76
_rtw_init_listhead(&precvbuf->list);
77
78
_rtw_spinlock_init(&precvbuf->recvbuf_lock);
79
80
precvbuf->alloc_sz = MAX_RECVBUF_SZ;
81
82
res = rtw_os_recvbuf_resource_alloc(padapter, precvbuf);
83
if (res == _FAIL)
84
break;
85
86
precvbuf->ref_cnt = 0;
87
precvbuf->adapter = padapter;
88
89
/* rtw_list_insert_tail(&precvbuf->list, &(precvpriv->free_recv_buf_queue.queue)); */
90
91
precvbuf++;
92
}
93
94
precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
95
96
#if defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD)
97
98
skb_queue_head_init(&precvpriv->rx_skb_queue);
99
100
#ifdef CONFIG_RX_INDICATE_QUEUE
101
memset(&precvpriv->rx_indicate_queue, 0, sizeof(struct ifqueue));
102
mtx_init(&precvpriv->rx_indicate_queue.ifq_mtx, "rx_indicate_queue", NULL, MTX_DEF);
103
#endif /* CONFIG_RX_INDICATE_QUEUE */
104
105
#ifdef CONFIG_PREALLOC_RECV_SKB
106
{
107
int i;
108
SIZE_PTR tmpaddr = 0;
109
SIZE_PTR alignment = 0;
110
struct sk_buff *pskb = NULL;
111
112
RTW_INFO("NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB);
113
#ifdef CONFIG_FIX_NR_BULKIN_BUFFER
114
RTW_INFO("Enable CONFIG_FIX_NR_BULKIN_BUFFER\n");
115
#endif
116
117
for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
118
#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
119
pskb = rtw_alloc_skb_premem(MAX_RECVBUF_SZ);
120
#else
121
pskb = rtw_skb_alloc(MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
122
#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */
123
124
if (pskb) {
125
#ifdef PLATFORM_FREEBSD
126
pskb->dev = padapter->pifp;
127
#else
128
pskb->dev = padapter->pnetdev;
129
#endif /* PLATFORM_FREEBSD */
130
131
#ifndef CONFIG_PREALLOC_RX_SKB_BUFFER
132
tmpaddr = (SIZE_PTR)pskb->data;
133
alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
134
skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
135
#endif
136
skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
137
}
138
}
139
}
140
#endif /* CONFIG_PREALLOC_RECV_SKB */
141
142
#endif /* defined(PLATFORM_LINUX) || defined(PLATFORM_FREEBSD) */
143
144
exit:
145
146
return res;
147
}
148
149
void usb_free_recv_priv(_adapter *padapter, u16 ini_in_buf_sz)
150
{
151
int i;
152
struct recv_buf *precvbuf;
153
struct recv_priv *precvpriv = &padapter->recvpriv;
154
155
precvbuf = (struct recv_buf *)precvpriv->precv_buf;
156
157
for (i = 0; i < NR_RECVBUFF ; i++) {
158
rtw_os_recvbuf_resource_free(padapter, precvbuf);
159
precvbuf++;
160
}
161
162
if (precvpriv->pallocated_recv_buf)
163
rtw_mfree(precvpriv->pallocated_recv_buf, NR_RECVBUFF * sizeof(struct recv_buf) + 4);
164
165
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
166
#ifdef PLATFORM_LINUX
167
if (precvpriv->int_in_urb)
168
usb_free_urb(precvpriv->int_in_urb);
169
#endif
170
if (precvpriv->int_in_buf)
171
rtw_mfree(precvpriv->int_in_buf, ini_in_buf_sz);
172
#endif /* CONFIG_USB_INTERRUPT_IN_PIPE */
173
174
#ifdef PLATFORM_LINUX
175
176
if (skb_queue_len(&precvpriv->rx_skb_queue))
177
RTW_WARN("rx_skb_queue not empty\n");
178
179
rtw_skb_queue_purge(&precvpriv->rx_skb_queue);
180
181
if (skb_queue_len(&precvpriv->free_recv_skb_queue))
182
RTW_WARN("free_recv_skb_queue not empty, %d\n", skb_queue_len(&precvpriv->free_recv_skb_queue));
183
184
#if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
185
#if defined(CONFIG_PREALLOC_RECV_SKB) && defined(CONFIG_PREALLOC_RX_SKB_BUFFER)
186
{
187
struct sk_buff *skb;
188
189
while ((skb = skb_dequeue(&precvpriv->free_recv_skb_queue)) != NULL) {
190
if (rtw_free_skb_premem(skb) != 0)
191
rtw_skb_free(skb);
192
}
193
}
194
#else
195
rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
196
#endif /* defined(CONFIG_PREALLOC_RX_SKB_BUFFER) && defined(CONFIG_PREALLOC_RECV_SKB) */
197
#endif /* !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX) */
198
199
#endif /* PLATFORM_LINUX */
200
201
#ifdef PLATFORM_FREEBSD
202
struct sk_buff *pskb;
203
while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue)))
204
rtw_skb_free(pskb);
205
206
#if !defined(CONFIG_USE_USB_BUFFER_ALLOC_RX)
207
rtw_skb_queue_purge(&precvpriv->free_recv_skb_queue);
208
#endif
209
210
#ifdef CONFIG_RX_INDICATE_QUEUE
211
struct mbuf *m;
212
for (;;) {
213
IF_DEQUEUE(&precvpriv->rx_indicate_queue, m);
214
if (m == NULL)
215
break;
216
rtw_os_pkt_free(m);
217
}
218
mtx_destroy(&precvpriv->rx_indicate_queue.ifq_mtx);
219
#endif /* CONFIG_RX_INDICATE_QUEUE */
220
221
#endif /* PLATFORM_FREEBSD */
222
}
223
224
#ifdef CONFIG_FW_C2H_REG
225
void usb_c2h_hisr_hdl(_adapter *adapter, u8 *buf)
226
{
227
u8 *c2h_evt = buf;
228
u8 id, seq, plen;
229
u8 *payload;
230
231
if (rtw_hal_c2h_reg_hdr_parse(adapter, buf, &id, &seq, &plen, &payload) != _SUCCESS)
232
return;
233
234
if (0)
235
RTW_PRINT("%s C2H == %d\n", __func__, id);
236
237
if (rtw_hal_c2h_id_handle_directly(adapter, id, seq, plen, payload)) {
238
/* Handle directly */
239
rtw_hal_c2h_handler(adapter, id, seq, plen, payload);
240
241
/* Replace with special pointer to trigger c2h_evt_clear only */
242
if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)&adapter->evtpriv) != _SUCCESS)
243
RTW_ERR("%s rtw_cbuf_push fail\n", __func__);
244
} else {
245
c2h_evt = rtw_malloc(C2H_REG_LEN);
246
if (c2h_evt != NULL) {
247
_rtw_memcpy(c2h_evt, buf, C2H_REG_LEN);
248
if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)c2h_evt) != _SUCCESS)
249
RTW_ERR("%s rtw_cbuf_push fail\n", __func__);
250
} else {
251
/* Error handling for malloc fail */
252
if (rtw_cbuf_push(adapter->evtpriv.c2h_queue, (void*)NULL) != _SUCCESS)
253
RTW_ERR("%s rtw_cbuf_push fail\n", __func__);
254
}
255
}
256
_set_workitem(&adapter->evtpriv.c2h_wk);
257
}
258
#endif
259
260
#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
261
int usb_write_async(struct usb_device *udev, u32 addr, void *pdata, u16 len)
262
{
263
u8 request;
264
u8 requesttype;
265
u16 wvalue;
266
u16 index;
267
int ret;
268
269
requesttype = VENDOR_WRITE;/* write_out */
270
request = REALTEK_USB_VENQT_CMD_REQ;
271
index = REALTEK_USB_VENQT_CMD_IDX;/* n/a */
272
273
wvalue = (u16)(addr & 0x0000ffff);
274
275
ret = _usbctrl_vendorreq_async_write(udev, request, wvalue, index, pdata, len, requesttype);
276
277
return ret;
278
}
279
280
int usb_async_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
281
{
282
u8 data;
283
int ret;
284
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
285
struct usb_device *udev = pdvobjpriv->pusbdev;
286
287
data = val;
288
ret = usb_write_async(udev, addr, &data, 1);
289
290
return ret;
291
}
292
293
int usb_async_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
294
{
295
u16 data;
296
int ret;
297
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
298
struct usb_device *udev = pdvobjpriv->pusbdev;
299
300
data = val;
301
ret = usb_write_async(udev, addr, &data, 2);
302
303
return ret;
304
}
305
306
int usb_async_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
307
{
308
u32 data;
309
int ret;
310
struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)pintfhdl->pintf_dev;
311
struct usb_device *udev = pdvobjpriv->pusbdev;
312
313
data = val;
314
ret = usb_write_async(udev, addr, &data, 4);
315
316
return ret;
317
}
318
#endif /* CONFIG_USB_SUPPORT_ASYNC_VDN_REQ */
319
320
u8 usb_read8(struct intf_hdl *pintfhdl, u32 addr)
321
{
322
u8 request;
323
u8 requesttype;
324
u16 wvalue;
325
u16 index;
326
u16 len;
327
u8 data = 0;
328
329
330
request = 0x05;
331
requesttype = 0x01;/* read_in */
332
index = 0;/* n/a */
333
334
wvalue = (u16)(addr & 0x0000ffff);
335
len = 1;
336
337
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
338
#if defined(CONFIG_RTL8710B)
339
if(wvalue >= 0x0000 && wvalue < 0x0100)
340
wvalue |= 0x8000;
341
#endif
342
343
usbctrl_vendorreq(pintfhdl, request, wvalue, index,
344
&data, len, requesttype);
345
346
347
return data;
348
}
349
350
u16 usb_read16(struct intf_hdl *pintfhdl, u32 addr)
351
{
352
u8 request;
353
u8 requesttype;
354
u16 wvalue;
355
u16 index;
356
u16 len;
357
u16 data = 0;
358
359
360
request = 0x05;
361
requesttype = 0x01;/* read_in */
362
index = 0;/* n/a */
363
364
wvalue = (u16)(addr & 0x0000ffff);
365
len = 2;
366
367
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
368
#if defined(CONFIG_RTL8710B)
369
if(wvalue >= 0x0000 && wvalue < 0x0100)
370
wvalue |= 0x8000;
371
#endif
372
373
usbctrl_vendorreq(pintfhdl, request, wvalue, index,
374
&data, len, requesttype);
375
376
377
return data;
378
379
}
380
381
u32 usb_read32(struct intf_hdl *pintfhdl, u32 addr)
382
{
383
u8 request;
384
u8 requesttype;
385
u16 wvalue;
386
u16 index;
387
u16 len;
388
u32 data = 0;
389
390
391
request = 0x05;
392
requesttype = 0x01;/* read_in */
393
index = 0;/* n/a */
394
395
wvalue = (u16)(addr & 0x0000ffff);
396
len = 4;
397
398
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
399
#if defined(CONFIG_RTL8710B)
400
if(wvalue >= 0x0000 && wvalue < 0x0100)
401
wvalue |= 0x8000;
402
#endif
403
404
usbctrl_vendorreq(pintfhdl, request, wvalue, index,
405
&data, len, requesttype);
406
407
408
return data;
409
}
410
411
int usb_write8(struct intf_hdl *pintfhdl, u32 addr, u8 val)
412
{
413
u8 request;
414
u8 requesttype;
415
u16 wvalue;
416
u16 index;
417
u16 len;
418
u8 data;
419
int ret;
420
421
422
request = 0x05;
423
requesttype = 0x00;/* write_out */
424
index = 0;/* n/a */
425
426
wvalue = (u16)(addr & 0x0000ffff);
427
len = 1;
428
data = val;
429
430
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
431
#if defined(CONFIG_RTL8710B)
432
if(wvalue >= 0x0000 && wvalue < 0x0100)
433
wvalue |= 0x8000;
434
#endif
435
436
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
437
&data, len, requesttype);
438
439
440
return ret;
441
}
442
443
int usb_write16(struct intf_hdl *pintfhdl, u32 addr, u16 val)
444
{
445
u8 request;
446
u8 requesttype;
447
u16 wvalue;
448
u16 index;
449
u16 len;
450
u16 data;
451
int ret;
452
453
454
request = 0x05;
455
requesttype = 0x00;/* write_out */
456
index = 0;/* n/a */
457
458
wvalue = (u16)(addr & 0x0000ffff);
459
len = 2;
460
data = val;
461
462
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
463
#if defined(CONFIG_RTL8710B)
464
if(wvalue >= 0x0000 && wvalue < 0x0100)
465
wvalue |= 0x8000;
466
#endif
467
468
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
469
&data, len, requesttype);
470
471
472
return ret;
473
474
}
475
476
int usb_write32(struct intf_hdl *pintfhdl, u32 addr, u32 val)
477
{
478
u8 request;
479
u8 requesttype;
480
u16 wvalue;
481
u16 index;
482
u16 len;
483
u32 data;
484
int ret;
485
486
487
request = 0x05;
488
requesttype = 0x00;/* write_out */
489
index = 0;/* n/a */
490
491
wvalue = (u16)(addr & 0x0000ffff);
492
len = 4;
493
data = val;
494
495
/* WLANON PAGE0_REG needs to add an offset 0x8000 */
496
#if defined(CONFIG_RTL8710B)
497
if(wvalue >= 0x0000 && wvalue < 0x0100)
498
wvalue |= 0x8000;
499
#endif
500
501
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
502
&data, len, requesttype);
503
504
505
return ret;
506
507
}
508
509
int usb_writeN(struct intf_hdl *pintfhdl, u32 addr, u32 length, u8 *pdata)
510
{
511
u8 request;
512
u8 requesttype;
513
u16 wvalue;
514
u16 index;
515
u16 len;
516
u8 buf[VENDOR_CMD_MAX_DATA_LEN] = {0};
517
int ret;
518
519
520
request = 0x05;
521
requesttype = 0x00;/* write_out */
522
index = 0;/* n/a */
523
524
wvalue = (u16)(addr & 0x0000ffff);
525
len = length;
526
_rtw_memcpy(buf, pdata, len);
527
ret = usbctrl_vendorreq(pintfhdl, request, wvalue, index,
528
buf, len, requesttype);
529
530
531
return ret;
532
}
533
534
void usb_set_intf_ops(_adapter *padapter, struct _io_ops *pops)
535
{
536
_rtw_memset((u8 *)pops, 0, sizeof(struct _io_ops));
537
538
pops->_read8 = &usb_read8;
539
pops->_read16 = &usb_read16;
540
pops->_read32 = &usb_read32;
541
pops->_read_mem = &usb_read_mem;
542
pops->_read_port = &usb_read_port;
543
544
pops->_write8 = &usb_write8;
545
pops->_write16 = &usb_write16;
546
pops->_write32 = &usb_write32;
547
pops->_writeN = &usb_writeN;
548
549
#ifdef CONFIG_USB_SUPPORT_ASYNC_VDN_REQ
550
pops->_write8_async = &usb_async_write8;
551
pops->_write16_async = &usb_async_write16;
552
pops->_write32_async = &usb_async_write32;
553
#endif
554
pops->_write_mem = &usb_write_mem;
555
pops->_write_port = &usb_write_port;
556
557
pops->_read_port_cancel = &usb_read_port_cancel;
558
pops->_write_port_cancel = &usb_write_port_cancel;
559
560
#ifdef CONFIG_USB_INTERRUPT_IN_PIPE
561
pops->_read_interrupt = &usb_read_interrupt;
562
#endif
563
564
}
565
566