~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/staging/usbip/userspace/src/usbip_network.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * Copyright (C) 2005-2007 Takahiro Hirofuchi
 
4
 */
 
5
 
 
6
#include "usbip_network.h"
 
7
 
 
8
void pack_uint32_t(int pack, uint32_t *num)
 
9
{
 
10
        uint32_t i;
 
11
 
 
12
        if (pack)
 
13
                i = htonl(*num);
 
14
        else
 
15
                i = ntohl(*num);
 
16
 
 
17
        *num = i;
 
18
}
 
19
 
 
20
void pack_uint16_t(int pack, uint16_t *num)
 
21
{
 
22
        uint16_t i;
 
23
 
 
24
        if (pack)
 
25
                i = htons(*num);
 
26
        else
 
27
                i = ntohs(*num);
 
28
 
 
29
        *num = i;
 
30
}
 
31
 
 
32
void pack_usb_device(int pack, struct usb_device *udev)
 
33
{
 
34
        pack_uint32_t(pack, &udev->busnum);
 
35
        pack_uint32_t(pack, &udev->devnum);
 
36
        pack_uint32_t(pack, &udev->speed );
 
37
 
 
38
        pack_uint16_t(pack, &udev->idVendor );
 
39
        pack_uint16_t(pack, &udev->idProduct);
 
40
        pack_uint16_t(pack, &udev->bcdDevice);
 
41
}
 
42
 
 
43
void pack_usb_interface(int pack __attribute__((unused)),
 
44
                        struct usb_interface *udev __attribute__((unused)))
 
45
{
 
46
        /* uint8_t members need nothing */
 
47
}
 
48
 
 
49
 
 
50
static ssize_t usbip_xmit(int sockfd, void *buff, size_t bufflen, int sending)
 
51
{
 
52
        ssize_t total = 0;
 
53
 
 
54
        if (!bufflen)
 
55
                return 0;
 
56
 
 
57
        do {
 
58
                ssize_t nbytes;
 
59
 
 
60
                if (sending)
 
61
                        nbytes = send(sockfd, buff, bufflen, 0);
 
62
                else
 
63
                        nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
 
64
 
 
65
                if (nbytes <= 0)
 
66
                        return -1;
 
67
 
 
68
                buff    = (void *) ((intptr_t) buff + nbytes);
 
69
                bufflen -= nbytes;
 
70
                total   += nbytes;
 
71
 
 
72
        } while (bufflen > 0);
 
73
 
 
74
 
 
75
        return total;
 
76
}
 
77
 
 
78
ssize_t usbip_recv(int sockfd, void *buff, size_t bufflen)
 
79
{
 
80
        return usbip_xmit(sockfd, buff, bufflen, 0);
 
81
}
 
82
 
 
83
ssize_t usbip_send(int sockfd, void *buff, size_t bufflen)
 
84
{
 
85
        return usbip_xmit(sockfd, buff, bufflen, 1);
 
86
}
 
87
 
 
88
int usbip_send_op_common(int sockfd, uint32_t code, uint32_t status)
 
89
{
 
90
        int ret;
 
91
        struct op_common op_common;
 
92
 
 
93
        bzero(&op_common, sizeof(op_common));
 
94
 
 
95
        op_common.version       = USBIP_VERSION;
 
96
        op_common.code          = code;
 
97
        op_common.status        = status;
 
98
 
 
99
        PACK_OP_COMMON(1, &op_common);
 
100
 
 
101
        ret = usbip_send(sockfd, (void *) &op_common, sizeof(op_common));
 
102
        if (ret < 0) {
 
103
                err("send op_common");
 
104
                return -1;
 
105
        }
 
106
 
 
107
        return 0;
 
108
}
 
109
 
 
110
int usbip_recv_op_common(int sockfd, uint16_t *code)
 
111
{
 
112
        int ret;
 
113
        struct op_common op_common;
 
114
 
 
115
        bzero(&op_common, sizeof(op_common));
 
116
 
 
117
        ret = usbip_recv(sockfd, (void *) &op_common, sizeof(op_common));
 
118
        if (ret < 0) {
 
119
                err("recv op_common, %d", ret);
 
120
                goto err;
 
121
        }
 
122
 
 
123
        PACK_OP_COMMON(0, &op_common);
 
124
 
 
125
        if (op_common.version != USBIP_VERSION) {
 
126
                err("version mismatch, %d %d", op_common.version, USBIP_VERSION);
 
127
                goto err;
 
128
        }
 
129
 
 
130
        switch(*code) {
 
131
                case OP_UNSPEC:
 
132
                        break;
 
133
                default:
 
134
                        if (op_common.code != *code) {
 
135
                                info("unexpected pdu %d for %d", op_common.code, *code);
 
136
                                goto err;
 
137
                        }
 
138
        }
 
139
 
 
140
        if (op_common.status != ST_OK) {
 
141
                info("request failed at peer, %d", op_common.status);
 
142
                goto err;
 
143
        }
 
144
 
 
145
        *code = op_common.code;
 
146
 
 
147
        return 0;
 
148
err:
 
149
        return -1;
 
150
}
 
151
 
 
152
 
 
153
int usbip_set_reuseaddr(int sockfd)
 
154
{
 
155
        const int val = 1;
 
156
        int ret;
 
157
 
 
158
        ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
 
159
        if (ret < 0)
 
160
                err("setsockopt SO_REUSEADDR");
 
161
 
 
162
        return ret;
 
163
}
 
164
 
 
165
int usbip_set_nodelay(int sockfd)
 
166
{
 
167
        const int val = 1;
 
168
        int ret;
 
169
 
 
170
        ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
 
171
        if (ret < 0)
 
172
                err("setsockopt TCP_NODELAY");
 
173
 
 
174
        return ret;
 
175
}
 
176
 
 
177
int usbip_set_keepalive(int sockfd)
 
178
{
 
179
        const int val = 1;
 
180
        int ret;
 
181
 
 
182
        ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
 
183
        if (ret < 0)
 
184
                err("setsockopt SO_KEEPALIVE");
 
185
 
 
186
        return ret;
 
187
}
 
188
 
 
189
/* IPv6 Ready */
 
190
/*
 
191
 * moved here from vhci_attach.c
 
192
 */
 
193
int tcp_connect(char *hostname, char *service)
 
194
{
 
195
        struct addrinfo hints, *res, *res0;
 
196
        int sockfd;
 
197
        int err;
 
198
 
 
199
 
 
200
        memset(&hints, 0, sizeof(hints));
 
201
        hints.ai_socktype = SOCK_STREAM;
 
202
 
 
203
        /* get all possible addresses */
 
204
        err = getaddrinfo(hostname, service, &hints, &res0);
 
205
        if (err) {
 
206
                err("%s %s: %s", hostname, service, gai_strerror(err));
 
207
                return -1;
 
208
        }
 
209
 
 
210
        /* try all the addresses */
 
211
        for (res = res0; res; res = res->ai_next) {
 
212
                char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
 
213
 
 
214
                err = getnameinfo(res->ai_addr, res->ai_addrlen,
 
215
                                hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
 
216
                if (err) {
 
217
                        err("%s %s: %s", hostname, service, gai_strerror(err));
 
218
                        continue;
 
219
                }
 
220
 
 
221
                dbg("trying %s port %s\n", hbuf, sbuf);
 
222
 
 
223
                sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
224
                if (sockfd < 0) {
 
225
                        err("socket");
 
226
                        continue;
 
227
                }
 
228
 
 
229
                /* should set TCP_NODELAY for usbip */
 
230
                usbip_set_nodelay(sockfd);
 
231
                /* TODO: write code for heatbeat */
 
232
                usbip_set_keepalive(sockfd);
 
233
 
 
234
                err = connect(sockfd, res->ai_addr, res->ai_addrlen);
 
235
                if (err < 0) {
 
236
                        close(sockfd);
 
237
                        continue;
 
238
                }
 
239
 
 
240
                /* connected */
 
241
                dbg("connected to %s:%s", hbuf, sbuf);
 
242
                freeaddrinfo(res0);
 
243
                return sockfd;
 
244
        }
 
245
 
 
246
 
 
247
        dbg("%s:%s, %s", hostname, service, "no destination to connect to");
 
248
        freeaddrinfo(res0);
 
249
 
 
250
        return -1;
 
251
}