-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcommon.c
120 lines (95 loc) · 2.91 KB
/
common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "msg.h"
#include "common.h"
#include "types.h"
#include "debug.h"
#define CONFIG_COMMON_DEBUG
#ifndef CONFIG_COMMON_DEBUG_LEVEL
#define CONFIG_COMMON_DEBUG_LEVEL INFO
#endif
#ifdef CONFIG_COMMON_DEBUG
#define log(id,lvl,fmt, ...) _log(id,CONFIG_COMMON_DEBUG_LEVEL,lvl,fmt, ##__VA_ARGS__)
#define log_msg(id,lvl,buf,fmt, ...) _log_msg(id,CONFIG_COMMON_DEBUG_LEVEL,lvl,buf,fmt, ##__VA_ARGS__)
#else
#define log(id,lvl,fmt, ...) {}
#define log_msg(id,lvl,buf,fmt, ...) {}
#endif
/* -------------------------------------------------------------------------------
*
* Endpoint Management
*
*--------------------------------------------------------------------------------
*/
#define SIZE_DEBUG_ENDPOINT 256
static char debug_endpoint[SIZE_DEBUG_ENDPOINT];
char* dump_endpoint_id(const epid_t *ep)
{
snprintf(debug_endpoint,SIZE_DEBUG_ENDPOINT,"ep:%u type:%s dir:%s",ep->num,EP_TYPE_STR(ep->type),EP_DIR_STR(ep->dir));
return debug_endpoint;
}
int _create_endpoint(ep_t *ep, const epnum_t epnum, const eptype_t eptype, const epdir_t epdir,
const struct usb_endpoint_descriptor *desc, cb_conf_t *callbacks)
{
ep->epid.num = epnum;
ep->epid.dir = epdir;
ep->epid.type = eptype;
if (desc) {
ep->desc = kmalloc(sizeof *desc,GFP_ATOMIC);
if (!ep->desc) {
goto fail1;
}
memcpy((void*)ep->desc,desc,sizeof *desc);
} else {
ep->desc = NULL;
}
ep->name = kmalloc(128,GFP_KERNEL);
if(!ep->name) {
goto fail2;
}
snprintf(ep->name,128,"%s%d_%s",EP_TYPE_STR(ep->epid.type),ep->epid.num,EP_DIR_STR(ep->epid.dir));
INIT_LIST_HEAD(&ep->reqlist);
ep->wq = create_workqueue(ep->name);
ep->ops = &((*callbacks)[eptype]);
return 0;
fail2:
kfree(ep->name);
fail1:
return -ENOMEM;
}
int create_ep0_endpoint(ep_t *ep, const epdir_t epdir, cb_conf_t *callbacks) {
return _create_endpoint(ep, 0, CTRL, epdir, NULL, callbacks);
}
int create_endpoint(ep_t *ep, const struct usb_endpoint_descriptor *desc, cb_conf_t *callbacks) {
epnum_t epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
eptype_t eptype = EP_TYPE_FROM_KERNEL(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
epdir_t epdir = EP_DIR_FROM_KERNEL(desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK);
return _create_endpoint(ep, epnum, eptype, epdir, desc, callbacks);
}
void free_endpoint(ep_t *ep)
{
if (ep->desc) {
kfree(ep->desc);
}
flush_workqueue(ep->wq);
destroy_workqueue(ep->wq);
kfree(ep->name);
}
ep_t* find_endpoint(const epid_t *id, struct list_head *list)
{
ep_t *ep;
list_for_each_entry(ep,list,list) {
if(id->num == ep->epid.num && id->type == ep->epid.type && id->dir == ep->epid.dir) {
return ep;
}
}
return NULL;
}
/* Send messsage to userland */
int send_userland(com_t *com, msg_t *msg)
{
ssize_t sz;
sz = com->send(com,msg);
if (sz < 0) {
return -EAGAIN;
}
return sz;
}