diff options
Diffstat (limited to 'utils/hwstub/lib')
-rw-r--r-- | utils/hwstub/lib/Makefile | 27 | ||||
-rw-r--r-- | utils/hwstub/lib/hwemul.c | 175 | ||||
-rw-r--r-- | utils/hwstub/lib/hwemul.h | 63 | ||||
-rw-r--r-- | utils/hwstub/lib/hwemul_protocol.h | 1 |
4 files changed, 266 insertions, 0 deletions
diff --git a/utils/hwstub/lib/Makefile b/utils/hwstub/lib/Makefile new file mode 100644 index 0000000000..7280fe8e38 --- /dev/null +++ b/utils/hwstub/lib/Makefile | |||
@@ -0,0 +1,27 @@ | |||
1 | CC=gcc | ||
2 | AR=ar | ||
3 | CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC | ||
4 | LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC | ||
5 | LIB=libhwemul.a | ||
6 | REGTOOLS=../../regtools | ||
7 | DESC=$(REGTOOLS)/desc | ||
8 | HWEMULGEN=$(REGTOOLS)/hwemulgen | ||
9 | HWEMULSOC_PREFIX=hwemul_soc | ||
10 | SRC=$(wildcard *.c) $(HWEMULSOC_PREFIX).c | ||
11 | OBJ=$(SRC:.c=.o) | ||
12 | |||
13 | all: $(LIB) $(EXEC) | ||
14 | |||
15 | $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h: | ||
16 | $(HWEMULGEN) $(DESC)/*.xml $(HWEMULSOC_PREFIX) | ||
17 | |||
18 | %.o: %.c $(HWEMULSOC_PREFIX).h | ||
19 | $(CC) $(CFLAGS) -c -o $@ $< | ||
20 | |||
21 | $(LIB): $(OBJ) | ||
22 | $(AR) rcs $@ $^ | ||
23 | |||
24 | clean: | ||
25 | rm -rf $(OBJ) $(LIB) $(HWEMULSOC_PREFIX).c $(HWEMULSOC_PREFIX).h | ||
26 | |||
27 | |||
diff --git a/utils/hwstub/lib/hwemul.c b/utils/hwstub/lib/hwemul.c new file mode 100644 index 0000000000..3e2e6de38a --- /dev/null +++ b/utils/hwstub/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 */ | ||
29 | int 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 | |||
76 | int hwemul_release(struct hwemul_device_t *dev) | ||
77 | { | ||
78 | return libusb_release_interface(dev->handle, dev->intf); | ||
79 | } | ||
80 | |||
81 | int 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 | |||
88 | int 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 | |||
95 | int 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 | |||
115 | int 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 | |||
123 | int 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 | |||
131 | const 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 | |||
142 | const 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 | |||
162 | int 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 | } | ||
diff --git a/utils/hwstub/lib/hwemul.h b/utils/hwstub/lib/hwemul.h new file mode 100644 index 0000000000..376ba65381 --- /dev/null +++ b/utils/hwstub/lib/hwemul.h | |||
@@ -0,0 +1,63 @@ | |||
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 | #ifndef __HWEMUL__ | ||
22 | #define __HWEMUL__ | ||
23 | |||
24 | #include <libusb.h> | ||
25 | #include "hwemul_protocol.h" | ||
26 | #include "hwemul_soc.h" | ||
27 | |||
28 | /** | ||
29 | * | ||
30 | * Low-Level interface | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | struct hwemul_device_t | ||
35 | { | ||
36 | libusb_device_handle *handle; | ||
37 | int intf; | ||
38 | int bulk_in; | ||
39 | int bulk_out; | ||
40 | int int_in; | ||
41 | }; | ||
42 | |||
43 | /* Requires then ->handle field only. Returns 0 on success */ | ||
44 | int hwemul_probe(struct hwemul_device_t *dev); | ||
45 | /* Returns 0 on success */ | ||
46 | int hwemul_release(struct hwemul_device_t *dev); | ||
47 | |||
48 | /* Returns number of bytes filled */ | ||
49 | int hwemul_get_info(struct hwemul_device_t *dev, uint16_t idx, void *info, size_t sz); | ||
50 | /* Returns number of bytes filled */ | ||
51 | int hwemul_get_log(struct hwemul_device_t *dev, void *buf, size_t sz); | ||
52 | /* Returns number of bytes written/read or <0 on error */ | ||
53 | int hwemul_rw_mem(struct hwemul_device_t *dev, int read, uint32_t addr, void *buf, size_t sz); | ||
54 | /* Returns <0 on error */ | ||
55 | int hwemul_call(struct hwemul_device_t *dev, uint32_t addr); | ||
56 | int hwemul_jump(struct hwemul_device_t *dev, uint32_t addr); | ||
57 | /* Returns <0 on error. The size must be a multiple of 16. */ | ||
58 | int hwemul_aes_otp(struct hwemul_device_t *dev, void *buf, size_t sz, uint16_t param); | ||
59 | |||
60 | const char *hwemul_get_product_string(struct usb_resp_info_stmp_t *stmp); | ||
61 | const char *hwemul_get_rev_string(struct usb_resp_info_stmp_t *stmp); | ||
62 | |||
63 | #endif /* __HWEMUL__ */ \ No newline at end of file | ||
diff --git a/utils/hwstub/lib/hwemul_protocol.h b/utils/hwstub/lib/hwemul_protocol.h new file mode 100644 index 0000000000..d3ffb6ce00 --- /dev/null +++ b/utils/hwstub/lib/hwemul_protocol.h | |||
@@ -0,0 +1 @@ | |||
#include "../hwemul_protocol.h" | |||