diff options
Diffstat (limited to 'utils/hwstub/lib/hwstub.c')
-rw-r--r-- | utils/hwstub/lib/hwstub.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c new file mode 100644 index 0000000000..92010e710b --- /dev/null +++ b/utils/hwstub/lib/hwstub.c | |||
@@ -0,0 +1,174 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2012 by Amaury Pouly | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "hwstub.h" | ||
22 | |||
23 | #ifndef MIN | ||
24 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) | ||
25 | #endif | ||
26 | |||
27 | /* requires then ->handle field only */ | ||
28 | int hwstub_probe(struct hwstub_device_t *dev) | ||
29 | { | ||
30 | libusb_device *mydev = libusb_get_device(dev->handle); | ||
31 | |||
32 | int config_id; | ||
33 | libusb_get_configuration(dev->handle, &config_id); | ||
34 | struct libusb_config_descriptor *config; | ||
35 | libusb_get_active_config_descriptor(mydev, &config); | ||
36 | |||
37 | const struct libusb_endpoint_descriptor *endp = NULL; | ||
38 | int intf; | ||
39 | for(intf = 0; intf < config->bNumInterfaces; intf++) | ||
40 | { | ||
41 | if(config->interface[intf].num_altsetting != 1) | ||
42 | continue; | ||
43 | const struct libusb_interface_descriptor *interface = | ||
44 | &config->interface[intf].altsetting[0]; | ||
45 | if(interface->bNumEndpoints != 3 || | ||
46 | interface->bInterfaceClass != HWSTUB_CLASS || | ||
47 | interface->bInterfaceSubClass != HWSTUB_SUBCLASS || | ||
48 | interface->bInterfaceProtocol != HWSTUB_PROTOCOL) | ||
49 | continue; | ||
50 | dev->intf = intf; | ||
51 | dev->bulk_in = dev->bulk_out = dev->int_in = -1; | ||
52 | for(int ep = 0; ep < interface->bNumEndpoints; ep++) | ||
53 | { | ||
54 | endp = &interface->endpoint[ep]; | ||
55 | if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT && | ||
56 | (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) | ||
57 | dev->int_in = endp->bEndpointAddress; | ||
58 | if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK && | ||
59 | (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) | ||
60 | dev->bulk_in = endp->bEndpointAddress; | ||
61 | if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK && | ||
62 | (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) | ||
63 | dev->bulk_out = endp->bEndpointAddress; | ||
64 | } | ||
65 | if(dev->bulk_in == -1 || dev->bulk_out == -1 || dev->int_in == -1) | ||
66 | continue; | ||
67 | break; | ||
68 | } | ||
69 | if(intf == config->bNumInterfaces) | ||
70 | return 1; | ||
71 | |||
72 | return libusb_claim_interface(dev->handle, intf); | ||
73 | } | ||
74 | |||
75 | int hwstub_release(struct hwstub_device_t *dev) | ||
76 | { | ||
77 | return libusb_release_interface(dev->handle, dev->intf); | ||
78 | } | ||
79 | |||
80 | int hwstub_get_info(struct hwstub_device_t *dev, uint16_t idx, void *info, size_t sz) | ||
81 | { | ||
82 | return libusb_control_transfer(dev->handle, | ||
83 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, | ||
84 | HWSTUB_GET_INFO, 0, idx, info, sz, 1000); | ||
85 | } | ||
86 | |||
87 | int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) | ||
88 | { | ||
89 | return libusb_control_transfer(dev->handle, | ||
90 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, | ||
91 | HWSTUB_GET_LOG, 0, 0, buf, sz, 1000); | ||
92 | } | ||
93 | |||
94 | int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) | ||
95 | { | ||
96 | size_t tot_sz = 0; | ||
97 | while(sz) | ||
98 | { | ||
99 | uint16_t xfer = MIN(1 * 1024, sz); | ||
100 | int ret = libusb_control_transfer(dev->handle, | ||
101 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | ||
102 | (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT), | ||
103 | HWSTUB_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000); | ||
104 | if(ret != xfer) | ||
105 | return ret; | ||
106 | sz -= xfer; | ||
107 | addr += xfer; | ||
108 | buf += xfer; | ||
109 | tot_sz += xfer; | ||
110 | } | ||
111 | return tot_sz; | ||
112 | } | ||
113 | |||
114 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr) | ||
115 | { | ||
116 | return libusb_control_transfer(dev->handle, | ||
117 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | ||
118 | LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0, | ||
119 | 1000); | ||
120 | } | ||
121 | |||
122 | int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr) | ||
123 | { | ||
124 | return libusb_control_transfer(dev->handle, | ||
125 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | ||
126 | LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0, | ||
127 | 1000); | ||
128 | } | ||
129 | |||
130 | const char *hwstub_get_product_string(struct usb_resp_info_stmp_t *stmp) | ||
131 | { | ||
132 | switch(stmp->chipid) | ||
133 | { | ||
134 | case 0x3700: return "STMP 3700"; | ||
135 | case 0x37b0: return "STMP 3770"; | ||
136 | case 0x3780: return "STMP 3780 / i.MX233"; | ||
137 | default: return "unknown"; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | const char *hwstub_get_rev_string(struct usb_resp_info_stmp_t *stmp) | ||
142 | { | ||
143 | switch(stmp->chipid) | ||
144 | { | ||
145 | case 0x37b0: | ||
146 | case 0x3780: | ||
147 | switch(stmp->rev) | ||
148 | { | ||
149 | case 0: return "TA1"; | ||
150 | case 1: return "TA2"; | ||
151 | case 2: return "TA3"; | ||
152 | case 3: return "TA4"; | ||
153 | default: return "unknown"; | ||
154 | } | ||
155 | break; | ||
156 | default: | ||
157 | return "unknown"; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | int hwstub_aes_otp(struct hwstub_device_t *dev, void *buf, size_t sz, uint16_t param) | ||
162 | { | ||
163 | int ret = libusb_control_transfer(dev->handle, | ||
164 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | ||
165 | LIBUSB_ENDPOINT_OUT, HWSTUB_AES_OTP, param, 0, buf, sz, | ||
166 | 1000); | ||
167 | if(ret <0 || (unsigned)ret != sz) | ||
168 | return -1; | ||
169 | int xfer; | ||
170 | ret = libusb_interrupt_transfer(dev->handle, dev->int_in, buf, sz, &xfer, 1000); | ||
171 | if(ret < 0 || (unsigned)xfer != sz) | ||
172 | return -1; | ||
173 | return ret; | ||
174 | } | ||