summaryrefslogtreecommitdiff
path: root/utils/imxtools/hwemul/lib/hwemul.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/imxtools/hwemul/lib/hwemul.c')
-rw-r--r--utils/imxtools/hwemul/lib/hwemul.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/utils/imxtools/hwemul/lib/hwemul.c b/utils/imxtools/hwemul/lib/hwemul.c
new file mode 100644
index 0000000000..3e2e6de38a
--- /dev/null
+++ b/utils/imxtools/hwemul/lib/hwemul.c
@@ -0,0 +1,175 @@
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 "hwemul.h"
22#include "hwemul_soc.h"
23
24#ifndef MIN
25#define MIN(a,b) ((a) < (b) ? (a) : (b))
26#endif
27
28/* requires then ->handle field only */
29int hwemul_probe(struct hwemul_device_t *dev)
30{
31 libusb_device *mydev = libusb_get_device(dev->handle);
32
33 int config_id;
34 libusb_get_configuration(dev->handle, &config_id);
35 struct libusb_config_descriptor *config;
36 libusb_get_active_config_descriptor(mydev, &config);
37
38 const struct libusb_endpoint_descriptor *endp = NULL;
39 int intf;
40 for(intf = 0; intf < config->bNumInterfaces; intf++)
41 {
42 if(config->interface[intf].num_altsetting != 1)
43 continue;
44 const struct libusb_interface_descriptor *interface =
45 &config->interface[intf].altsetting[0];
46 if(interface->bNumEndpoints != 3 ||
47 interface->bInterfaceClass != HWEMUL_CLASS ||
48 interface->bInterfaceSubClass != HWEMUL_SUBCLASS ||
49 interface->bInterfaceProtocol != HWEMUL_PROTOCOL)
50 continue;
51 dev->intf = intf;
52 dev->bulk_in = dev->bulk_out = dev->int_in = -1;
53 for(int ep = 0; ep < interface->bNumEndpoints; ep++)
54 {
55 endp = &interface->endpoint[ep];
56 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT &&
57 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
58 dev->int_in = endp->bEndpointAddress;
59 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
60 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN)
61 dev->bulk_in = endp->bEndpointAddress;
62 if((endp->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_BULK &&
63 (endp->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT)
64 dev->bulk_out = endp->bEndpointAddress;
65 }
66 if(dev->bulk_in == -1 || dev->bulk_out == -1 || dev->int_in == -1)
67 continue;
68 break;
69 }
70 if(intf == config->bNumInterfaces)
71 return 1;
72
73 return libusb_claim_interface(dev->handle, intf);
74}
75
76int hwemul_release(struct hwemul_device_t *dev)
77{
78 return libusb_release_interface(dev->handle, dev->intf);
79}
80
81int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz)
82{
83 return libusb_control_transfer(dev->handle,
84 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
85 HWEMUL_GET_INFO, 0, idx, info, sz, 1000);
86}
87
88int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz)
89{
90 return libusb_control_transfer(dev->handle,
91 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
92 HWEMUL_GET_LOG, 0, 0, buf, sz, 1000);
93}
94
95int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
96{
97 size_t tot_sz = 0;
98 while(sz)
99 {
100 uint16_t xfer = MIN(1 * 1024, sz);
101 int ret = libusb_control_transfer(dev->handle,
102 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
103 (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT),
104 HWEMUL_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000);
105 if(ret != xfer)
106 return ret;
107 sz -= xfer;
108 addr += xfer;
109 buf += xfer;
110 tot_sz += xfer;
111 }
112 return tot_sz;
113}
114
115int hwemul_call(struct hwemul_device_t *dev, uint32_t addr)
116{
117 return libusb_control_transfer(dev->handle,
118 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
119 LIBUSB_ENDPOINT_OUT, HWEMUL_CALL, addr & 0xffff, addr >> 16, NULL, 0,
120 1000);
121}
122
123int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr)
124{
125 return libusb_control_transfer(dev->handle,
126 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
127 LIBUSB_ENDPOINT_OUT, HWEMUL_JUMP, addr & 0xffff, addr >> 16, NULL, 0,
128 1000);
129}
130
131const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp)
132{
133 switch(stmp->chipid)
134 {
135 case 0x3700: return "STMP 3700";
136 case 0x37b0: return "STMP 3770";
137 case 0x3780: return "STMP 3780 / i.MX233";
138 default: return "unknown";
139 }
140}
141
142const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp)
143{
144 switch(stmp->chipid)
145 {
146 case 0x37b0:
147 case 0x3780:
148 switch(stmp->rev)
149 {
150 case 0: return "TA1";
151 case 1: return "TA2";
152 case 2: return "TA3";
153 case 3: return "TA4";
154 default: return "unknown";
155 }
156 break;
157 default:
158 return "unknown";
159 }
160}
161
162int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param)
163{
164 int ret = libusb_control_transfer(dev->handle,
165 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE |
166 LIBUSB_ENDPOINT_OUT, HWEMUL_AES_OTP, param, 0, buf, sz,
167 1000);
168 if(ret <0 || (unsigned)ret != sz)
169 return -1;
170 int xfer;
171 ret = libusb_interrupt_transfer(dev->handle, dev->int_in, buf, sz, &xfer, 1000);
172 if(ret < 0 || (unsigned)xfer != sz)
173 return -1;
174 return ret;
175}