summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/hwstub/include/hwstub.h70
-rw-r--r--utils/hwstub/lib/Makefile13
-rw-r--r--utils/hwstub/lib/hwstub.c255
3 files changed, 3 insertions, 335 deletions
diff --git a/utils/hwstub/include/hwstub.h b/utils/hwstub/include/hwstub.h
deleted file mode 100644
index 4d12de8eda..0000000000
--- a/utils/hwstub/include/hwstub.h
+++ /dev/null
@@ -1,70 +0,0 @@
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 __HWSTUB__
22#define __HWSTUB__
23
24#include <libusb.h>
25#include "hwstub_protocol.h"
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/**
32 *
33 * Low-Level interface
34 *
35 */
36
37struct hwstub_device_t;
38
39/* Returns hwstub interface, or -1 if none was found */
40int hwstub_probe(libusb_device *dev);
41/* Helper function which returns a list of all hwstub devices found. The caller
42 * must unref all of them when done, possibly using libusb_free_device_list().
43 * Return number of devices or <0 on error */
44ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list);
45/* Returns NULL on error */
46struct hwstub_device_t *hwstub_open(libusb_device_handle *handle);
47/* Returns 0 on success. Does *NOT* close the usb handle */
48int hwstub_release(struct hwstub_device_t *dev);
49
50/* Returns number of bytes filled */
51int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz);
52/* Returns number of bytes filled */
53int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz);
54/* Returns number of bytes written/read or <0 on error */
55int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
56int hwstub_read_atomic(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz);
57int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz);
58int hwstub_write_atomic(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz);
59int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
60int hwstub_rw_mem_atomic(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz);
61/* Returns <0 on error */
62int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags);
63int hwstub_call(struct hwstub_device_t *dev, uint32_t addr);
64int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr);
65
66#ifdef __cplusplus
67} // extern "C"
68#endif
69
70#endif /* __HWSTUB__ */ \ No newline at end of file
diff --git a/utils/hwstub/lib/Makefile b/utils/hwstub/lib/Makefile
index 92dd358ce3..1cc61d6d20 100644
--- a/utils/hwstub/lib/Makefile
+++ b/utils/hwstub/lib/Makefile
@@ -1,19 +1,14 @@
1AR=ar 1AR=ar
2INCLUDE=../include 2INCLUDE=../include
3CFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c99 -g -fPIC -D_XOPEN_SOURCE=700 -I$(INCLUDE)
4CXXFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c++11 -g -fPIC -D_XOPEN_SOURCE=700 -I$(INCLUDE) 3CXXFLAGS=-W -Wall -O2 `pkg-config --cflags libusb-1.0` -std=c++11 -g -fPIC -D_XOPEN_SOURCE=700 -I$(INCLUDE)
5LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC -lpthread 4LDFLAGS=`pkg-config --libs libusb-1.0` -fPIC -lpthread
6LIB=libhwstub.a 5LIB=libhwstub.a
7SRC=$(wildcard *.c) 6SRC=$(wildcard *.cpp)
8SRCXX=$(wildcard *.cpp) 7OBJ=$(SRC:.cpp=.o)
9OBJ=$(SRCXX:.cpp=.oxx) $(SRCXX:.cpp=.o)
10 8
11all: $(LIB) 9all: $(LIB)
12 10
13%.o: %.c 11%.o: %.cpp
14 $(CC) $(CFLAGS) -c -o $@ $<
15
16%.oxx: %.cpp
17 $(CXX) $(CXXFLAGS) -c -o $@ $< 12 $(CXX) $(CXXFLAGS) -c -o $@ $<
18 13
19$(LIB): $(OBJ) 14$(LIB): $(OBJ)
@@ -21,5 +16,3 @@ $(LIB): $(OBJ)
21 16
22clean: 17clean:
23 rm -rf $(OBJ) $(LIB) 18 rm -rf $(OBJ) $(LIB)
24
25
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c
deleted file mode 100644
index d3908585da..0000000000
--- a/utils/hwstub/lib/hwstub.c
+++ /dev/null
@@ -1,255 +0,0 @@
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#include <string.h>
23#include <stdlib.h>
24
25#ifndef MIN
26#define MIN(a,b) ((a) <= (b) ? (a) : (b))
27#endif
28
29struct hwstub_device_t
30{
31 libusb_device_handle *handle;
32 int intf;
33 unsigned buf_sz;
34 uint16_t id;
35 uint8_t minor_ver;
36};
37
38int hwstub_probe(libusb_device *dev)
39{
40 struct libusb_config_descriptor *config = NULL;
41 int ret = -1;
42 if(libusb_get_config_descriptor(dev, 0, &config) != 0)
43 goto Lend;
44 /* search hwstub interface */
45 for(unsigned i = 0; i < config->bNumInterfaces; i++)
46 {
47 /* hwstub interface has only one setting */
48 if(config->interface[i].num_altsetting != 1)
49 continue;
50 const struct libusb_interface_descriptor *intf = &config->interface[i].altsetting[0];
51 /* check class/subclass/protocol */
52 if(intf->bInterfaceClass != HWSTUB_CLASS ||
53 intf->bInterfaceSubClass != HWSTUB_SUBCLASS ||
54 intf->bInterfaceProtocol != HWSTUB_PROTOCOL)
55 continue;
56 /* found ! */
57 ret = i;
58 break;
59 }
60Lend:
61 if(config)
62 libusb_free_config_descriptor(config);
63 return ret;
64}
65
66ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list)
67{
68 libusb_device **great_list;
69 ssize_t great_cnt = libusb_get_device_list(ctx, &great_list);
70 if(great_cnt < 0)
71 return great_cnt;
72 /* allocate a list (size at least one NULL entry at the end) */
73 libusb_device **mylist = malloc(sizeof(libusb_device *) * (great_cnt + 1));
74 memset(mylist, 0, sizeof(libusb_device *) * (great_cnt + 1));
75 /* list hwstub devices */
76 ssize_t cnt = 0;
77 for(int i = 0; i < great_cnt; i++)
78 if(hwstub_probe(great_list[i]) >= 0)
79 {
80 libusb_ref_device(great_list[i]);
81 mylist[cnt++] = great_list[i];
82 }
83 /* free old list */
84 libusb_free_device_list(great_list, 1);
85 /* return */
86 *list = mylist;
87 return cnt;
88}
89
90struct hwstub_device_t *hwstub_open(libusb_device_handle *handle)
91{
92 struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t));
93 memset(dev, 0, sizeof(struct hwstub_device_t));
94 dev->handle = handle;
95 dev->intf = -1;
96 dev->buf_sz = 1024; /* default size */
97 libusb_device *mydev = libusb_get_device(dev->handle);
98 dev->intf = hwstub_probe(mydev);
99 if(dev->intf == -1)
100 goto Lerr;
101 /* try to get version */
102 struct hwstub_version_desc_t m_hwdev_ver;
103 int sz = hwstub_get_desc(dev, HWSTUB_DT_VERSION, &m_hwdev_ver, sizeof(m_hwdev_ver));
104 if(sz != sizeof(m_hwdev_ver))
105 goto Lerr;
106 /* major version must match, minor version is taken to be the minimum between
107 * what library and device support */
108 if(m_hwdev_ver.bMajor != HWSTUB_VERSION_MAJOR)
109 goto Lerr;
110 dev->minor_ver = MIN(m_hwdev_ver.bMinor, HWSTUB_VERSION_MINOR);
111 /* try to get actual buffer size */
112 struct hwstub_layout_desc_t layout;
113 sz = hwstub_get_desc(dev, HWSTUB_DT_LAYOUT, &layout, sizeof(layout));
114 if(sz == (int)sizeof(layout))
115 dev->buf_sz = layout.dBufferSize;
116 return dev;
117
118Lerr:
119 free(dev);
120 return NULL;
121}
122
123int hwstub_release(struct hwstub_device_t *dev)
124{
125 free(dev);
126 return 0;
127}
128
129int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz)
130{
131 return libusb_control_transfer(dev->handle,
132 LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
133 LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, dev->intf, info, sz, 1000);
134}
135
136int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz)
137{
138 return libusb_control_transfer(dev->handle,
139 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
140 HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000);
141}
142
143static int _hwstub_read(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr,
144 void *buf, size_t sz)
145{
146 struct hwstub_read_req_t read;
147 read.dAddress = addr;
148 int size = libusb_control_transfer(dev->handle,
149 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
150 HWSTUB_READ, dev->id, dev->intf, (void *)&read, sizeof(read), 1000);
151 if(size != (int)sizeof(read))
152 return -1;
153 return libusb_control_transfer(dev->handle,
154 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
155 breq, dev->id++, dev->intf, buf, sz, 1000);
156}
157
158static int _hwstub_write(struct hwstub_device_t *dev, uint8_t breq, uint32_t addr,
159 const void *buf, size_t sz)
160{
161 size_t hdr_sz = sizeof(struct hwstub_write_req_t);
162 struct hwstub_write_req_t *req = malloc(sz + hdr_sz);
163 req->dAddress = addr;
164 memcpy(req + 1, buf, sz);
165 int size = libusb_control_transfer(dev->handle,
166 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
167 breq, dev->id++, dev->intf, (void *)req, sz + hdr_sz, 1000);
168 free(req);
169 return size - hdr_sz;
170}
171
172int hwstub_read_atomic(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
173{
174 /* reject any read greater than the buffer, it makes no sense anyway */
175 if(sz > dev->buf_sz)
176 return -1;
177 return _hwstub_read(dev, HWSTUB_READ2_ATOMIC, addr, buf, sz);
178}
179
180int hwstub_write_atomic(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz)
181{
182 /* reject any write greater than the buffer, it makes no sense anyway */
183 if(sz + sizeof(struct hwstub_write_req_t) > dev->buf_sz)
184 return -1;
185 return _hwstub_write(dev, HWSTUB_WRITE_ATOMIC, addr, buf, sz);
186}
187
188/* Intermediate function which make sure we don't overflow the device buffer */
189int hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz)
190{
191 int cnt = 0;
192 while(sz > 0)
193 {
194 int xfer = _hwstub_read(dev, HWSTUB_READ2, addr, buf, MIN(sz, dev->buf_sz));
195 if(xfer < 0)
196 return xfer;
197 sz -= xfer;
198 buf += xfer;
199 addr += xfer;
200 cnt += xfer;
201 }
202 return cnt;
203}
204
205/* Intermediate function which make sure we don't overflow the device buffer */
206int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, const void *buf, size_t sz)
207{
208 int cnt = 0;
209 while(sz > 0)
210 {
211 int xfer = _hwstub_write(dev, HWSTUB_WRITE, addr, buf,
212 MIN(sz, dev->buf_sz - sizeof(struct hwstub_write_req_t)));
213 if(xfer < 0)
214 return xfer;
215 sz -= xfer;
216 buf += xfer;
217 addr += xfer;
218 cnt += xfer;
219 }
220 return cnt;
221}
222
223int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
224{
225 return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz);
226}
227
228int hwstub_rw_mem_atomic(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz)
229{
230 return read ? hwstub_read_atomic(dev, addr, buf, sz) :
231 hwstub_write_atomic(dev, addr, buf, sz);
232}
233
234int hwstub_exec(struct hwstub_device_t *dev, uint32_t addr, uint16_t flags)
235{
236 struct hwstub_exec_req_t exec;
237 exec.dAddress = addr;
238 exec.bmFlags = flags;
239 int size = libusb_control_transfer(dev->handle,
240 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
241 HWSTUB_EXEC, dev->id, dev->intf, (void *)&exec, sizeof(exec), 1000);
242 if(size != (int)sizeof(exec))
243 return -1;
244 return 0;
245}
246
247int hwstub_call(struct hwstub_device_t *dev, uint32_t addr)
248{
249 return hwstub_exec(dev, addr, HWSTUB_EXEC_CALL);
250}
251
252int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr)
253{
254 return hwstub_exec(dev, addr, HWSTUB_EXEC_JUMP);
255}