blob: 8ad5a0e9c6be6e971e18b942cff362c537148dc8 [file] [log] [blame]
Kévin Redon9a12d682018-07-08 13:21:16 +02001/* USB buffer library
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
16 */
Harald Welte8e7fca32017-05-07 16:14:33 +020017#include "board.h"
18#include "trace.h"
19#include "usb_buf.h"
Kévin Redona1012b12018-07-01 18:11:01 +020020#include "simtrace_usb.h"
Harald Welte8e7fca32017-05-07 16:14:33 +020021
Harald Welte9d90d282018-06-29 22:25:42 +020022#include <osmocom/core/linuxlist.h>
23#include <osmocom/core/msgb.h>
Harald Welte8e7fca32017-05-07 16:14:33 +020024#include <errno.h>
25
26#define USB_ALLOC_SIZE 280
27
28static struct usb_buffered_ep usb_buffered_ep[BOARD_USB_NUMENDPOINTS];
29
30struct usb_buffered_ep *usb_get_buf_ep(uint8_t ep)
31{
32 if (ep >= ARRAY_SIZE(usb_buffered_ep))
33 return NULL;
34 return &usb_buffered_ep[ep];
35}
36
37
38/***********************************************************************
39 * User API
40 ***********************************************************************/
41
42struct llist_head *usb_get_queue(uint8_t ep)
43{
44 struct usb_buffered_ep *bep = usb_get_buf_ep(ep);
45 if (!bep)
46 return NULL;
47 return &bep->queue;
48}
49
50/* allocate a USB buffer for use with given end-point */
51struct msgb *usb_buf_alloc(uint8_t ep)
52{
53 struct msgb *msg;
54
55 msg = msgb_alloc(USB_ALLOC_SIZE, "USB");
56 if (!msg)
57 return NULL;
58 msg->dst = usb_get_buf_ep(ep);
59 return msg;
60}
61
62/* release/return the USB buffer to the pool */
63void usb_buf_free(struct msgb *msg)
64{
65 msgb_free(msg);
66}
67
68/* submit a USB buffer for transmission to host */
69int usb_buf_submit(struct msgb *msg)
70{
71 struct usb_buffered_ep *ep = msg->dst;
72
73 if (!msg->dst) {
74 TRACE_ERROR("%s: msg without dst\r\n", __func__);
75 usb_buf_free(msg);
76 return -EINVAL;
77 }
78
79 /* no need for irqsafe operation, as the usb_tx_queue is
80 * processed only by the main loop context */
Harald Weltef4a625b2019-12-14 19:07:57 +010081 msgb_enqueue_count(&ep->queue, msg, &ep->queue_len);
Harald Welte8e7fca32017-05-07 16:14:33 +020082 return 0;
83}
84
85void usb_buf_init(void)
86{
87 unsigned int i;
88
89 for (i = 0; i < ARRAY_SIZE(usb_buffered_ep); i++) {
90 struct usb_buffered_ep *ep = &usb_buffered_ep[i];
91 INIT_LLIST_HEAD(&ep->queue);
92 }
93}