1 /*
2  * USB device handling
3  *
4  * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
5  */
6 
7 #include "internal.h"
8 #include <sys/poll.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <fcntl.h>
12 
13 /*
14  * Send/receive USB control block
15  */
ifd_usb_control(ifd_device_t * dev,unsigned int requesttype,unsigned int request,unsigned int value,unsigned int idx,void * buffer,size_t len,long timeout)16 int ifd_usb_control(ifd_device_t * dev, unsigned int requesttype,
17 		    unsigned int request, unsigned int value,
18 		    unsigned int idx, void *buffer, size_t len, long timeout)
19 {
20 	int n;
21 
22 	if (dev->type != IFD_DEVICE_TYPE_USB)
23 		return -1;
24 	if (timeout < 0)
25 		timeout = 10000;
26 
27 	if ((ct_config.debug >= 3) && !(requesttype & 0x80)) {
28 		ifd_debug(4,
29 			  "usb req type=x%02x req=x%02x val=x%04x ind=x%04x len=%u",
30 			  requesttype, request, value, idx, len);
31 		if (len)
32 			ifd_debug(4, "send %s", ct_hexdump(buffer, len));
33 	}
34 
35 	n = ifd_sysdep_usb_control(dev, requesttype, request, value, idx,
36 				   buffer, len, timeout);
37 
38 	if ((ct_config.debug >= 3) && (requesttype & 0x80)) {
39 		ifd_debug(4,
40 			  "usb req type=x%02x req=x%02x val=x%04x ind=x%04x len=%d",
41 			  requesttype, request, value, idx, n);
42 		if (n > 0)
43 			ifd_debug(4, "recv %s", ct_hexdump(buffer, n));
44 	}
45 
46 	return n;
47 }
48 
49 /*
50  * USB frame capture
51  */
ifd_usb_begin_capture(ifd_device_t * dev,int type,int endpoint,size_t maxpacket,ifd_usb_capture_t ** capret)52 int ifd_usb_begin_capture(ifd_device_t * dev, int type, int endpoint,
53 			  size_t maxpacket, ifd_usb_capture_t ** capret)
54 {
55 	if (dev->type != IFD_DEVICE_TYPE_USB)
56 		return -1;
57 
58 	if (ct_config.debug >= 5)
59 		ifd_debug(5, "usb capture type=%d ep=x%x maxpacket=%u",
60 			  type, endpoint, maxpacket);
61 	return ifd_sysdep_usb_begin_capture(dev, type, endpoint, maxpacket,
62 					    capret);
63 }
64 
ifd_usb_capture_event(ifd_device_t * dev,ifd_usb_capture_t * cap,void * buffer,size_t len)65 int ifd_usb_capture_event(ifd_device_t * dev, ifd_usb_capture_t * cap, void *buffer,
66 		    size_t len)
67 {
68 	int rc;
69 
70 	if (dev->type != IFD_DEVICE_TYPE_USB)
71 		return -1;
72 
73 	ifd_debug(5, "called.");
74 	rc = ifd_sysdep_usb_capture_event(dev, cap, buffer, len);
75 	if (ct_config.debug >= 3) {
76 		if (rc < 0)
77 			ifd_debug(1, "usb event capture: %s", ct_strerror(rc));
78 		if (rc > 0)
79 			ifd_debug(5, "usb event capture: recv %s",
80 				  ct_hexdump(buffer, rc));
81 		if (rc == 0)
82 			ifd_debug(5, "usb event capture: rc=%d (timeout?)", rc);
83 	}
84 	return rc;
85 }
86 
ifd_usb_capture(ifd_device_t * dev,ifd_usb_capture_t * cap,void * buffer,size_t len,long timeout)87 int ifd_usb_capture(ifd_device_t * dev, ifd_usb_capture_t * cap, void *buffer,
88 		    size_t len, long timeout)
89 {
90 	int rc;
91 
92 	if (dev->type != IFD_DEVICE_TYPE_USB)
93 		return -1;
94 
95 	ifd_debug(5, "called, timeout=%ld ms.", timeout);
96 	rc = ifd_sysdep_usb_capture(dev, cap, buffer, len, timeout);
97 	if (ct_config.debug >= 3) {
98 		if (rc < 0)
99 			ifd_debug(1, "usb capture: %s", ct_strerror(rc));
100 		if (rc > 0)
101 			ifd_debug(5, "usb capture: recv %s",
102 				  ct_hexdump(buffer, rc));
103 		if (rc == 0)
104 			ifd_debug(5, "usb capture: rc=%d (timeout?)", rc);
105 	}
106 	return rc;
107 }
108 
ifd_usb_end_capture(ifd_device_t * dev,ifd_usb_capture_t * cap)109 int ifd_usb_end_capture(ifd_device_t * dev, ifd_usb_capture_t * cap)
110 {
111 	ifd_debug(5, "called.");
112 
113 	if (dev->type != IFD_DEVICE_TYPE_USB)
114 		return -1;
115 	return ifd_sysdep_usb_end_capture(dev, cap);
116 }
117 
118 /*
119  * Set usb params (for now, endpoint for transceive)
120  */
usb_set_params(ifd_device_t * dev,const ifd_device_params_t * params)121 static int usb_set_params(ifd_device_t * dev,
122 			  const ifd_device_params_t * params)
123 {
124 
125 	ifd_debug(1, "called. config x%02x ifc x%02x eps x%02x/x%02x",
126 		  params->usb.configuration, params->usb.interface,
127 		  params->usb.ep_o, params->usb.ep_i);
128 	if (params->usb.interface != -1 && params->usb.interface > 255)
129 		return IFD_ERROR_INVALID_ARG;
130 	if (params->usb.ep_o != -1 && (params->usb.ep_o & ~0x7F))
131 		return IFD_ERROR_INVALID_ARG;
132 	if ((params->usb.ep_i != -1 && (params->usb.ep_i & ~0xFF))
133 	    || !(params->usb.ep_i & 0x80))
134 		return IFD_ERROR_INVALID_ARG;
135 
136 	if (dev->settings.usb.interface != -1)
137 		ifd_sysdep_usb_release_interface(dev,
138 						 dev->settings.usb.interface);
139 
140 	if (params->usb.configuration != -1
141 	    && ifd_sysdep_usb_set_configuration(dev, params->usb.configuration))
142 		return -1;
143 
144 	if (params->usb.interface != -1) {
145 		if (ifd_sysdep_usb_claim_interface(dev, params->usb.interface))
146 			return -1;
147 		if (params->usb.altsetting != -1
148 		    && ifd_sysdep_usb_set_interface(dev,
149 						    params->usb.interface,
150 						    params->usb.altsetting))
151 			return -1;
152 	}
153 
154 	dev->settings = *params;
155 	return 0;
156 }
157 
usb_send(ifd_device_t * dev,const unsigned char * send,size_t sendlen)158 static int usb_send(ifd_device_t * dev, const unsigned char *send,
159 		    size_t sendlen)
160 {
161 	if (dev->settings.usb.ep_o == -1)
162 		return IFD_ERROR_NOT_SUPPORTED;
163 	if (ct_config.debug >= 3) {
164 		ifd_debug(4, "usb send to=x%02x", dev->settings.usb.ep_o);
165 		if (sendlen)
166 			ifd_debug(4, "send %s", ct_hexdump(send, sendlen));
167 	}
168 
169 	return ifd_sysdep_usb_bulk(dev,
170 				   dev->settings.usb.ep_o,
171 				   (unsigned char *)send, sendlen, 10000);
172 }
173 
usb_recv(ifd_device_t * dev,unsigned char * recv,size_t recvlen,long timeout)174 static int usb_recv(ifd_device_t * dev, unsigned char *recv, size_t recvlen,
175 		    long timeout)
176 {
177 	int rc;
178 
179 	if (dev->settings.usb.ep_i == -1)
180 		return IFD_ERROR_NOT_SUPPORTED;
181 
182 	rc = ifd_sysdep_usb_bulk(dev, dev->settings.usb.ep_i,
183 				 recv, recvlen, timeout);
184 	if (rc >= 0 && ct_config.debug >= 4) {
185 		ifd_debug(4, "usb recv from=x%02x", dev->settings.usb.ep_i);
186 		if (rc > 0)
187 			ifd_debug(4, "recv %s", ct_hexdump(recv, rc));
188 	}
189 
190 	return rc;
191 }
192 
usb_reset(ifd_device_t * dev)193 static int usb_reset(ifd_device_t * dev)
194 {
195 	int rc;
196 
197 	rc = ifd_sysdep_usb_reset(dev);
198 
199 	return rc;
200 }
201 
usb_get_eventfd(ifd_device_t * dev,short * events)202 static int usb_get_eventfd(ifd_device_t * dev, short *events)
203 {
204 	int rc;
205 
206 	rc = ifd_sysdep_usb_get_eventfd(dev, events);
207 
208 	return rc;
209 }
210 
211 static struct ifd_device_ops ifd_usb_ops;
212 
213 /*
214  * Open USB device
215  */
ifd_open_usb(const char * device)216 ifd_device_t *ifd_open_usb(const char *device)
217 {
218 	ifd_device_t *dev;
219 	int fd;
220 
221 	if ((fd = ifd_sysdep_usb_open(device)) < 0) {
222 		ct_error("Unable to open USB device %s: %m", device);
223 		return NULL;
224 	}
225 
226 	ifd_usb_ops.poll_presence = ifd_sysdep_usb_poll_presence;
227 	ifd_usb_ops.set_params = usb_set_params;
228 	ifd_usb_ops.send = usb_send;
229 	ifd_usb_ops.recv = usb_recv;
230 	ifd_usb_ops.reset = usb_reset;
231 	ifd_usb_ops.get_eventfd = usb_get_eventfd;
232 
233 	dev = ifd_device_new(device, &ifd_usb_ops, sizeof(*dev));
234 	dev->type = IFD_DEVICE_TYPE_USB;
235 	dev->timeout = 10000;
236 	dev->fd = fd;
237 	dev->settings.usb.configuration = -1;
238 	dev->settings.usb.interface = -1;
239 	dev->settings.usb.altsetting = -1;
240 	dev->settings.usb.ep_o = -1;
241 	dev->settings.usb.ep_i = -1;
242 
243 	return dev;
244 }
245