summaryrefslogtreecommitdiff
path: root/utils/hwstub/lib/hwstub.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/hwstub/lib/hwstub.c')
-rw-r--r--utils/hwstub/lib/hwstub.c174
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 */
28int 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
75int hwstub_release(struct hwstub_device_t *dev)
76{
77 return libusb_release_interface(dev->handle, dev->intf);
78}
79
80int 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
87int 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
94int 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
114int 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
122int 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
130const 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
141const 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
161int 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}