Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
770 user890104 1
//
2
//
3
//    Copyright 2011 user890104
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "global.h"
25
 
26
#include "emcore.h"
27
#include "util.h"
28
#include "usb.h"
29
 
30
 
31
libusb_context* usb_ctx = NULL;
32
libusb_device_handle* usb_handle = NULL;
33
 
34
extern struct emcore_usb_endpoints_addr emcore_usb_eps_addr;
35
extern struct emcore_usb_endpoints_max_packet_size emcore_usb_eps_mps;
36
 
37
int usb_init(void)
38
{
39
    int res;
40
 
41
#ifdef DEBUG
42
    fprintf(stderr, "Initialising USB library...\n");
43
#endif
44
 
45
    res = libusb_init(&usb_ctx);
46
 
47
    if (LIBUSB_SUCCESS != res)
48
    {
49
        return res;
50
    }
51
 
52
#ifdef DEBUG
53
    fprintf(stderr, "USB library initialized!\n");
54
    libusb_set_debug(usb_ctx, 3);
55
 
56
#endif
57
 
58
    return LIBUSB_SUCCESS;
59
}
60
 
785 user890104 61
int usb_find(uint16_t vendor_id, uint16_t product_id, uint8_t* reattach)
770 user890104 62
{
63
    libusb_device **devs, *dev;
64
    ssize_t devs_cnt;
65
    int res, i;
66
    struct libusb_device_descriptor dev_desc;
67
    uint8_t found = 0;
68
    struct libusb_config_descriptor* cfg_desc;
69
    const struct libusb_interface* iface;
70
    const struct libusb_interface_descriptor* iface_desc;
71
    const struct libusb_endpoint_descriptor* ep_desc;
72
 
73
#ifdef DEBUG
74
    fprintf(stderr, "Getting USB device list...\n");
75
#endif
76
 
77
    devs_cnt = libusb_get_device_list(usb_ctx, &devs);
78
 
79
    if (devs_cnt < 0)
80
    {
81
        return devs_cnt;
82
    }
83
 
84
#ifdef DEBUG
85
    fprintf(stderr, "Found %d USB devices!\n", devs_cnt);
86
#endif
87
    for (i = 0; i < devs_cnt; ++i)
88
    {
89
        dev = devs[i];
90
#ifdef DEBUG
91
        fprintf(stderr, "Getting device descriptor of USB device %d...\n", i);
92
#endif
93
        res = libusb_get_device_descriptor(dev, &dev_desc);
94
 
95
        if (LIBUSB_SUCCESS != res)
96
        {
97
#ifdef DEBUG
98
            fprintf(stderr, "Unable to get device descriptor of device %d!\n", i);
99
#endif
100
            continue;
101
        }
102
 
103
#ifdef DEBUG
104
        fprintf(stderr, "[%04x:%04x] bus %d, device %d, USB ver. %04x\n", dev_desc.idVendor,
105
            dev_desc.idProduct, libusb_get_bus_number(dev),
106
            libusb_get_device_address(dev), dev_desc.bcdUSB);
107
#endif
108
        if (vendor_id == dev_desc.idVendor && product_id == dev_desc.idProduct)
109
        {
110
#ifdef DEBUG
111
            fprintf(stderr, "Found emCORE USB device!\n");
112
#endif
113
            if (1 != dev_desc.bNumConfigurations)
114
            {
115
#ifdef DEBUG
116
                fprintf(stderr, "Number of configs is different than 1, not the right device...\n");
117
#endif
118
                continue;
119
            }
120
 
121
#ifdef DEBUG
122
            fprintf(stderr, "Getting config descriptor 0 of device...\n");
123
#endif
124
 
125
            res = libusb_get_config_descriptor(dev, 0, &cfg_desc);
126
 
127
            if (LIBUSB_SUCCESS != res)
128
            {
129
                return res;
130
            }
131
 
132
            if (1 != cfg_desc->bNumInterfaces)
133
            {
134
#ifdef DEBUG
135
                fprintf(stderr, "Wrong USB device, it should have exactly 1 interface\n");
136
#endif
137
 
138
                continue;
139
            }
140
 
141
            iface = &cfg_desc->interface[0];
142
 
143
            if (1 != iface->num_altsetting)
144
            {
145
#ifdef DEBUG
146
                fprintf(stderr, "Wrong USB device, it should have exactly 1 altsetting\n");
147
#endif
148
 
149
                continue;
150
            }
151
 
152
            iface_desc = &iface->altsetting[0];
153
 
154
            if (4 != iface_desc->bNumEndpoints)
155
            {
156
#ifdef DEBUG
157
                fprintf(stderr, "Wrong USB device, it should have exactly 4 endpoints\n");
158
#endif
159
 
160
                continue;
161
            }
162
 
163
#ifdef DEBUG
164
           fprintf(stderr, "Endpoints:");
165
#endif
166
 
167
            for (i = 0; i < 4; ++i)
168
            {
169
                ep_desc = &iface_desc->endpoint[i];
170
 
171
#ifdef DEBUG
172
                fprintf(stderr, " %d at 0x%02x", i, ep_desc->bEndpointAddress);
173
#endif
174
 
175
                switch (i) {
176
                    case 0:
177
                        emcore_usb_eps_addr.cout = ep_desc->bEndpointAddress;
178
                    break;
179
                    case 1:
180
                        emcore_usb_eps_addr.cin = ep_desc->bEndpointAddress;
181
                    break;
182
                    case 2:
183
                        emcore_usb_eps_addr.dout = ep_desc->bEndpointAddress;
184
                    break;
185
                    case 3:
186
                        emcore_usb_eps_addr.din = ep_desc->bEndpointAddress;
187
                    break;
188
                }
189
            }
190
 
191
#ifdef DEBUG
192
            fprintf(stderr, "\n");
193
#endif
194
 
195
            found = 1;
196
        }
197
    }
198
 
199
    if (found)
200
    {
201
        res = usb_open(dev, reattach);
202
    }
203
    else
204
    {
205
        fprintf(stderr, "USB device with VID=%4x and PID=%4x not found!\n",
206
            vendor_id, product_id);
207
 
208
        res = EMCORE_ERROR_NO_DEVICE;
209
    }
210
 
211
#ifdef DEBUG
212
    fprintf(stderr, "Freeing device list...\n");
213
#endif
214
    libusb_free_device_list(devs, 1);
215
 
216
    return res;
217
}
218
 
219
int usb_open(libusb_device* dev, uint8_t* reattach)
220
{
221
    int res;
222
 
223
#ifdef DEBUG
224
    fprintf(stderr, "Opening USB device...\n");
225
#endif
226
    res = libusb_open(dev, &usb_handle);
227
 
228
    if (LIBUSB_SUCCESS != res)
229
    {
230
        return res;
231
    }
232
#ifdef DEBUG
233
    fprintf(stderr, "USB device opened!\n");
234
    fprintf(stderr, "Setting USB configuration 1...\n");
235
#endif
236
 
237
    res = libusb_set_configuration(usb_handle, 1);
238
 
239
    if (LIBUSB_SUCCESS != res)
240
    {
241
        return res;
242
    }
243
#ifdef DEBUG
244
    fprintf(stderr, "USB configuration set!\n");
245
#endif
246
    res = libusb_kernel_driver_active(usb_handle, 0);
247
 
248
    if (1 == res)
249
    {
250
        *reattach = 1;
251
 
252
        res = libusb_detach_kernel_driver(usb_handle, 0);
253
    }
254
 
255
    if (LIBUSB_SUCCESS != res)
256
    {
257
        return res;
258
    }
259
 
260
#ifdef DEBUG
261
    fprintf(stderr, "Claiming interface 0...\n");
262
#endif
263
    res = libusb_claim_interface(usb_handle, 0);
264
 
265
    if (LIBUSB_SUCCESS != res)
266
    {
267
        return res;
268
    }
269
 
270
#ifdef DEBUG
271
    fprintf(stderr, "Interface claimed successfully!\n");
272
    fprintf(stderr, "Getting endpoints max size...\n");
273
#endif
274
 
275
    res = emcore_get_packet_info(&emcore_usb_eps_mps);
276
 
277
    if (EMCORE_SUCCESS != res)
278
    {
279
        return res;
280
    }
281
 
282
#ifdef DEBUG
283
    fprintf(stderr, "Got endpoint max size!\n");
284
    fprintf(stderr, "COUT max pckt: %d, CIN max pckt: %d, DOUT max pckt: %d, DIN max pckt: %d\n",
285
        emcore_usb_eps_mps.cout, emcore_usb_eps_mps.cin, emcore_usb_eps_mps.dout, emcore_usb_eps_mps.din
286
    );
287
#endif
288
 
289
    return LIBUSB_SUCCESS;
290
}
291
 
785 user890104 292
int usb_bulk_transfer(unsigned char endpoint, void* data, int length)
770 user890104 293
{
294
    int transferred;
295
    int res;
296
 
297
    res = libusb_bulk_transfer(usb_handle, endpoint, (unsigned char*)data, length, &transferred, 30000);
298
 
299
    if (LIBUSB_SUCCESS != res)
300
    {
301
        return res;
302
    }
303
 
304
    if (transferred != length)
305
    {
306
        return EMCORE_ERROR_INCOMPLETE;
307
    }
308
 
309
    return LIBUSB_SUCCESS;
310
}
311
 
785 user890104 312
int usb_close(uint8_t reattach) {
770 user890104 313
    int res;
314
 
315
#ifdef DEBUG
316
    fprintf(stderr, "Releasing USB interface...\n");
317
#endif
318
    res = libusb_release_interface(usb_handle, 0);
319
 
320
    if (LIBUSB_SUCCESS != res)
321
    {
322
        return res;
323
    }
324
 
325
#ifdef DEBUG
326
    fprintf(stderr, "Released interface successfully!\n");
327
#endif
328
 
329
    if (reattach)
330
    {
331
#ifdef DEBUG
332
        fprintf(stderr, "Reattaching kernel driver...\n");
333
#endif
334
 
335
        res = libusb_attach_kernel_driver(usb_handle, 0);
336
 
337
        if (LIBUSB_SUCCESS == res)
338
        {
339
#ifdef DEBUG
340
            fprintf(stderr, "Reattached successfully!\n");
341
#endif
342
        }
343
        else
344
        {
345
            print_error(res);
346
 
347
            res = LIBUSB_SUCCESS;
348
        }
349
    }
350
#ifdef DEBUG
351
    fprintf(stderr, "Closing USB device handle...\n");
352
#endif
353
    libusb_close(usb_handle);
354
 
355
    return res;
356
}
357
 
358
void usb_exit(void)
359
{
360
#ifdef DEBUG
361
    fprintf(stderr, "Deinitializing USB library...\n");
362
#endif
363
 
364
    libusb_exit(usb_ctx);
365
}
366
 
785 user890104 367
int usb_destroy(uint8_t reattach)
770 user890104 368
{
369
    int res = LIBUSB_SUCCESS;
370
 
371
    if (usb_handle)
372
    {
373
        res = usb_close(reattach);
374
    }
375
 
376
    if (usb_ctx)
377
    {
378
        usb_exit();
379
    }
380
 
381
    return res;
382
}