diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-05-25 16:06:31 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-09-07 17:45:10 +0200 |
commit | 12ce7fc2cce5531723ea7d141df80142891989d7 (patch) | |
tree | dc4e3320f8ed0932265b3c917448a83f7dcecafe /utils/hwstub/lib/hwstub.c | |
parent | 1dc1a9310e8a078a633dd90def13103f80e01ce7 (diff) | |
download | rockbox-12ce7fc2cce5531723ea7d141df80142891989d7.tar.gz rockbox-12ce7fc2cce5531723ea7d141df80142891989d7.zip |
hwstub: remove protocol to make it use its own interface
This way, hwstub can be implemented along with other usb features/interfaces.
Change-Id: I7148cab845049cc0a8b8e740fa0d52d3a385eaed
Diffstat (limited to 'utils/hwstub/lib/hwstub.c')
-rw-r--r-- | utils/hwstub/lib/hwstub.c | 125 |
1 files changed, 94 insertions, 31 deletions
diff --git a/utils/hwstub/lib/hwstub.c b/utils/hwstub/lib/hwstub.c index 67a797ddfe..9f46159026 100644 --- a/utils/hwstub/lib/hwstub.c +++ b/utils/hwstub/lib/hwstub.c | |||
@@ -30,26 +30,78 @@ struct hwstub_device_t | |||
30 | { | 30 | { |
31 | libusb_device_handle *handle; | 31 | libusb_device_handle *handle; |
32 | int intf; | 32 | int intf; |
33 | int bulk_in; | 33 | unsigned buf_sz; |
34 | int bulk_out; | 34 | uint16_t id; |
35 | int int_in; | ||
36 | }; | 35 | }; |
37 | 36 | ||
37 | int hwstub_probe(libusb_device *dev) | ||
38 | { | ||
39 | struct libusb_config_descriptor *config = NULL; | ||
40 | int ret = -1; | ||
41 | if(libusb_get_config_descriptor(dev, 0, &config) != 0) | ||
42 | goto Lend; | ||
43 | /* search hwstub interface */ | ||
44 | for(unsigned i = 0; i < config->bNumInterfaces; i++) | ||
45 | { | ||
46 | /* hwstub interface has only one setting */ | ||
47 | if(config->interface[i].num_altsetting != 1) | ||
48 | continue; | ||
49 | const struct libusb_interface_descriptor *intf = &config->interface[i].altsetting[0]; | ||
50 | /* check class/subclass/protocol */ | ||
51 | if(intf->bInterfaceClass != HWSTUB_CLASS || | ||
52 | intf->bInterfaceSubClass != HWSTUB_SUBCLASS || | ||
53 | intf->bInterfaceProtocol != HWSTUB_PROTOCOL) | ||
54 | continue; | ||
55 | /* found ! */ | ||
56 | ret = i; | ||
57 | break; | ||
58 | } | ||
59 | Lend: | ||
60 | if(config) | ||
61 | libusb_free_config_descriptor(config); | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | ssize_t hwstub_get_device_list(libusb_context *ctx, libusb_device ***list) | ||
66 | { | ||
67 | libusb_device **great_list; | ||
68 | ssize_t great_cnt = libusb_get_device_list(ctx, &great_list); | ||
69 | if(great_cnt < 0) | ||
70 | return great_cnt; | ||
71 | /* allocate a list (size at least one NULL entry at the end) */ | ||
72 | libusb_device **mylist = malloc(sizeof(libusb_device *) * (great_cnt + 1)); | ||
73 | memset(mylist, 0, sizeof(libusb_device *) * (great_cnt + 1)); | ||
74 | /* list hwstub devices */ | ||
75 | ssize_t cnt = 0; | ||
76 | for(int i = 0; i < great_cnt; i++) | ||
77 | if(hwstub_probe(great_list[i]) >= 0) | ||
78 | { | ||
79 | libusb_ref_device(great_list[i]); | ||
80 | mylist[cnt++] = great_list[i]; | ||
81 | } | ||
82 | /* free old list */ | ||
83 | libusb_free_device_list(great_list, 1); | ||
84 | /* return */ | ||
85 | *list = mylist; | ||
86 | return cnt; | ||
87 | } | ||
88 | |||
38 | struct hwstub_device_t *hwstub_open(libusb_device_handle *handle) | 89 | struct hwstub_device_t *hwstub_open(libusb_device_handle *handle) |
39 | { | 90 | { |
40 | struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t)); | 91 | struct hwstub_device_t *dev = malloc(sizeof(struct hwstub_device_t)); |
41 | memset(dev, 0, sizeof(struct hwstub_device_t)); | 92 | memset(dev, 0, sizeof(struct hwstub_device_t)); |
42 | dev->handle = handle; | 93 | dev->handle = handle; |
94 | dev->intf = -1; | ||
95 | dev->buf_sz = 1024; /* default size */ | ||
43 | libusb_device *mydev = libusb_get_device(dev->handle); | 96 | libusb_device *mydev = libusb_get_device(dev->handle); |
44 | 97 | dev->intf = hwstub_probe(mydev); | |
45 | int config_id; | 98 | if(dev->intf == -1) |
46 | libusb_get_configuration(dev->handle, &config_id); | ||
47 | struct libusb_device_descriptor dev_desc; | ||
48 | libusb_get_device_descriptor(mydev, &dev_desc); | ||
49 | if(dev_desc.bDeviceClass != HWSTUB_CLASS || | ||
50 | dev_desc.bDeviceSubClass != HWSTUB_SUBCLASS || | ||
51 | dev_desc.bDeviceProtocol != HWSTUB_PROTOCOL) | ||
52 | goto Lerr; | 99 | goto Lerr; |
100 | /* try to get actual buffer size */ | ||
101 | struct hwstub_layout_desc_t layout; | ||
102 | int sz = hwstub_get_desc(dev, HWSTUB_DT_LAYOUT, &layout, sizeof(layout)); | ||
103 | if(sz == (int)sizeof(layout)) | ||
104 | dev->buf_sz = layout->dBufferSize; | ||
53 | return dev; | 105 | return dev; |
54 | 106 | ||
55 | Lerr: | 107 | Lerr: |
@@ -66,49 +118,60 @@ int hwstub_release(struct hwstub_device_t *dev) | |||
66 | int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz) | 118 | int hwstub_get_desc(struct hwstub_device_t *dev, uint16_t desc, void *info, size_t sz) |
67 | { | 119 | { |
68 | return libusb_control_transfer(dev->handle, | 120 | return libusb_control_transfer(dev->handle, |
69 | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, | 121 | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, |
70 | LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, 0, info, sz, 1000); | 122 | LIBUSB_REQUEST_GET_DESCRIPTOR, desc << 8, dev->intf, info, sz, 1000); |
71 | } | 123 | } |
72 | 124 | ||
73 | int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) | 125 | int hwstub_get_log(struct hwstub_device_t *dev, void *buf, size_t sz) |
74 | { | 126 | { |
75 | return libusb_control_transfer(dev->handle, | 127 | return libusb_control_transfer(dev->handle, |
76 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN, | 128 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, |
77 | HWSTUB_GET_LOG, 0, 0, buf, sz, 1000); | 129 | HWSTUB_GET_LOG, 0, dev->intf, buf, sz, 1000); |
130 | } | ||
131 | |||
132 | static int _hwstub_read(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | ||
133 | { | ||
134 | struct hwstub_read_req_t read; | ||
135 | read.dAddress = addr; | ||
136 | int size = libusb_control_transfer(dev->handle, | ||
137 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, | ||
138 | HWSTUB_READ, dev->id, dev->intf, &read, sizeof(read), 1000); | ||
139 | if(size != (int)sizeof(read)) | ||
140 | return -1; | ||
141 | return libusb_control_transfer(dev->handle, | ||
142 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, | ||
143 | HWSTUB_READ2, dev->id++, dev->intf, &read, sizeof(read), 1000); | ||
144 | } | ||
145 | |||
146 | int hwstub_write(struct hwstub_device_t *dev, uint32_t addr, void *buf, size_t sz) | ||
147 | { | ||
78 | } | 148 | } |
79 | 149 | ||
80 | int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) | 150 | int hwstub_rw_mem(struct hwstub_device_t *dev, int read, uint32_t addr, void *buf, size_t sz) |
81 | { | 151 | { |
82 | size_t tot_sz = 0; | 152 | return read ? hwstub_read(dev, addr, buf, sz) : hwstub_write(dev, addr, buf, sz); |
83 | while(sz) | ||
84 | { | ||
85 | uint16_t xfer = MIN(1 * 1024, sz); | ||
86 | int ret = libusb_control_transfer(dev->handle, | ||
87 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | ||
88 | (read ? LIBUSB_ENDPOINT_IN : LIBUSB_ENDPOINT_OUT), | ||
89 | HWSTUB_RW_MEM, addr & 0xffff, addr >> 16, buf, xfer, 1000); | ||
90 | if(ret != xfer) | ||
91 | return ret; | ||
92 | sz -= xfer; | ||
93 | addr += xfer; | ||
94 | buf += xfer; | ||
95 | tot_sz += xfer; | ||
96 | } | ||
97 | return tot_sz; | ||
98 | } | 153 | } |
99 | 154 | ||
100 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr) | 155 | int hwstub_call(struct hwstub_device_t *dev, uint32_t addr) |
101 | { | 156 | { |
157 | #if 0 | ||
102 | return libusb_control_transfer(dev->handle, | 158 | return libusb_control_transfer(dev->handle, |
103 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | 159 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | |
104 | LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0, | 160 | LIBUSB_ENDPOINT_OUT, HWSTUB_CALL, addr & 0xffff, addr >> 16, NULL, 0, |
105 | 1000); | 161 | 1000); |
162 | #else | ||
163 | return -1; | ||
164 | #endif | ||
106 | } | 165 | } |
107 | 166 | ||
108 | int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr) | 167 | int hwstub_jump(struct hwstub_device_t *dev, uint32_t addr) |
109 | { | 168 | { |
169 | #if 0 | ||
110 | return libusb_control_transfer(dev->handle, | 170 | return libusb_control_transfer(dev->handle, |
111 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | | 171 | LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_DEVICE | |
112 | LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0, | 172 | LIBUSB_ENDPOINT_OUT, HWSTUB_JUMP, addr & 0xffff, addr >> 16, NULL, 0, |
113 | 1000); | 173 | 1000); |
174 | #else | ||
175 | return -1; | ||
176 | #endif | ||
114 | } | 177 | } |