xref: /minix/minix/lib/libdevman/usb.c (revision 00b67f09)
1 #include <errno.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <minix/config.h>
6 #include <minix/const.h>
7 #include <minix/devman.h>
8 #include <minix/usb.h>
9 #include <minix/sysutil.h>
10 
11 #include "local.h"
12 
13 #define CHECKOUTOFMEM(ptr) if(ptr == NULL) \
14                                panic("Out of memory! (%s, line %d)", \
15 							     __FILE__, __LINE__)
16 
17 
18 static int (*bind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep);
19 static int (*unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep);
20 
21 /****************************************************************************
22  *    devman_usb_add_attr                                                   *
23  ***************************************************************************/
24 static void
25 devman_usb_add_attr
26 (struct devman_dev *dev, const char *name, const char *data)
27 {
28 	struct devman_static_attribute *attr = (struct devman_static_attribute *)
29 	    malloc(sizeof(struct devman_static_attribute));
30 
31 	CHECKOUTOFMEM(attr);
32 
33 	attr->name = malloc((strlen(name)+1)*sizeof(char));
34 	memcpy(attr->name, name, (strlen(name)+1));
35 
36 	attr->data = malloc((strlen(data)+1)*sizeof(char));
37 	memcpy(attr->data, data, (strlen(data)+1));
38 	TAILQ_INSERT_TAIL(&dev->attrs, attr, list);
39 }
40 
41 /****************************************************************************
42  *    add_device_attributes                                                 *
43  ***************************************************************************/
44 static void
45 add_device_attributes
46 (struct devman_usb_dev *udev)
47 {
48 	int ret;
49 	char data[32];
50 
51 	ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceClass);
52 	if (ret < 0) {
53 		panic("add_device_attributes: snprintf failed");
54 	}
55 	devman_usb_add_attr(udev->dev, "bDeviceClass", data);
56 
57 	ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceSubClass);
58 	if (ret < 0) {
59 		panic("add_device_attributes: snprintf failed");
60 	}
61 	devman_usb_add_attr(udev->dev, "bDeviceSubClass", data);
62 
63 	ret = snprintf(data,sizeof(data),"0x%02x",udev->desc->bDeviceProtocol);
64 	if (ret < 0) {
65 		panic("add_device_attributes: snprintf failed");
66 	}
67 	devman_usb_add_attr(udev->dev, "bDeviceProtocol", data);
68 
69 	ret = snprintf(data,sizeof(data),"0x%04x",UGETW(udev->desc->idVendor));
70 	if (ret < 0) {
71 		panic("add_device_attributes: snprintf failed");
72 	}
73 	devman_usb_add_attr(udev->dev, "idVendor", data);
74 
75 	ret = snprintf(data,sizeof(data),"0x%04x",UGETW(udev->desc->idProduct));
76 	if (ret < 0) {
77 		panic("add_device_attributes: snprintf failed");
78 	}
79 	devman_usb_add_attr(udev->dev, "idProduct", data);
80 
81 	if (udev->product)
82 		devman_usb_add_attr(udev->dev, "Product", udev->product);
83 	if (udev->manufacturer)
84 		devman_usb_add_attr(udev->dev, "Manufacturer", udev->manufacturer);
85 	if (udev->serial)
86 		devman_usb_add_attr(udev->dev, "SerialNumber", udev->serial);
87 	devman_usb_add_attr(udev->dev, "dev_type", "USB_DEV");
88 }
89 
90 /****************************************************************************
91  *     add_interface_attributes                                             *
92  ***************************************************************************/
93 static void
94 add_interface_attributes
95 (struct devman_usb_interface *intf)
96 {
97 	int ret;
98 	char data[32];
99 
100 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceNumber);
101 	if (ret < 0) {
102 		panic("add_device_attributes: snprintf failed");
103 	}
104 	devman_usb_add_attr(intf->dev, "bInterfaceNumber", data);
105 
106 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bAlternateSetting);
107 	if (ret < 0) {
108 		panic("add_device_attributes: snprintf failed");
109 	}
110 	devman_usb_add_attr(intf->dev, "bAlternateSetting", data);
111 
112 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bNumEndpoints);
113 	if (ret < 0) {
114 		panic("add_device_attributes: snprintf failed");
115 	}
116 	devman_usb_add_attr(intf->dev, "bNumEndpoints", data);
117 
118 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceClass);
119 	if (ret < 0) {
120 		panic("add_device_attributes: snprintf failed");
121 	}
122 	devman_usb_add_attr(intf->dev, "bInterfaceClass", data);
123 
124 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceSubClass);
125 	if (ret < 0) {
126 		panic("add_device_attributes: snprintf failed");
127 	}
128 	devman_usb_add_attr(intf->dev, "bInterfaceSubClass", data);
129 
130 	ret = snprintf(data,sizeof(data),"0x%02x",intf->desc->bInterfaceProtocol);
131 	if (ret < 0) {
132 		panic("add_device_attributes: snprintf failed");
133 	}
134 	devman_usb_add_attr(intf->dev, "bInterfaceProtocol", data);
135 
136 	devman_usb_add_attr(intf->dev, "dev_type", "USB_INTF");
137 }
138 
139 
140 /****************************************************************************
141  *      devman_usb_device_new                                               *
142  ***************************************************************************/
143 struct devman_usb_dev*
144 devman_usb_device_new
145 (int dev_id)
146 {
147 	struct devman_usb_dev *udev = NULL;
148 	struct devman_dev * dev = NULL;
149 
150 	udev = (struct devman_usb_dev *) malloc(sizeof(struct devman_usb_dev));
151 
152 	CHECKOUTOFMEM(udev);
153 
154 	/* allocate device */
155 	dev = (struct devman_dev *) malloc(sizeof(struct devman_dev));
156 
157 	CHECKOUTOFMEM(dev);
158 
159 	udev->dev_id = dev_id;
160 	udev->dev    = dev;
161 
162 	dev->parent_dev_id = 0; /* For now add it directly to the root dev */
163 
164 	snprintf(dev->name, DEVMAN_DEV_NAME_LEN, "USB%d", dev_id);
165 
166 	TAILQ_INIT(&dev->attrs);
167 
168 	return udev;
169 }
170 
171 /****************************************************************************
172  *     devman_usb_device_delete                                             *
173  ***************************************************************************/
174 void devman_usb_device_delete(struct devman_usb_dev *udev)
175 {
176 	int i;
177 	struct devman_static_attribute *attr,*temp;
178 
179 
180 	for (i=0; i < udev->intf_count; i++) {
181 		TAILQ_FOREACH_SAFE(attr, &udev->interfaces[i].dev->attrs, list, temp)
182 		{
183 			free(attr->name);
184 			free(attr->data);
185 			free(attr);
186 		}
187 		free(udev->interfaces[i].dev);
188 	}
189 
190 	TAILQ_FOREACH_SAFE(attr, &udev->dev->attrs, list, temp) {
191 		free(attr->name);
192 		free(attr->data);
193 		free(attr);
194 	}
195 
196 	free(udev->dev);
197 	free(udev);
198 }
199 
200 static int devman_usb_bind_cb(void *data, endpoint_t ep) {
201 	if (bind_cb) {
202 		return bind_cb((struct devman_usb_bind_cb_data *) data, ep);
203 	} else {
204 		return ENODEV;
205 	}
206 }
207 
208 static int devman_usb_unbind_cb(void *data, endpoint_t ep) {
209 	if (unbind_cb) {
210 		return unbind_cb((struct devman_usb_bind_cb_data *) data, ep);
211 	} else {
212 		return ENODEV;
213 	}
214 }
215 
216 /****************************************************************************
217  *     devman_usb_device_add                                                *
218  ***************************************************************************/
219 int devman_usb_device_add(struct devman_usb_dev *dev)
220 {
221 	int i,res = 0;
222 	add_device_attributes(dev);
223 
224 	/* add the USB device */
225 	dev->cb_data.dev_id    = dev->dev_id;
226 	dev->cb_data.interface = -1;
227 
228 	dev->dev->bind_cb   = devman_usb_bind_cb;
229 	dev->dev->unbind_cb = devman_usb_unbind_cb;
230 	dev->dev->data       = &dev->cb_data;
231 
232 	res = devman_add_device(dev->dev);
233 
234 	if (res != 0) {
235 		panic("devman_usb_device_add(): devman_add_device failed.");
236 	}
237 
238 	/* add the USB interfaces */
239 	for (i=0; i < dev->intf_count; i++) {
240 		/* prepare */
241 		dev->interfaces[i].dev =
242 		    (struct devman_dev *) malloc(sizeof(struct devman_dev));
243 		CHECKOUTOFMEM(dev->interfaces[i].dev);
244 
245 		TAILQ_INIT(&dev->interfaces[i].dev->attrs);
246 		snprintf(dev->interfaces[i].dev->name, DEVMAN_DEV_NAME_LEN,
247 		    "intf%d", i);
248 
249 		add_interface_attributes(&dev->interfaces[i]);
250 
251 		dev->interfaces[i].dev->parent_dev_id = dev->dev->dev_id;
252 
253 
254 		dev->interfaces[i].cb_data.dev_id    = dev->dev_id;
255 		dev->interfaces[i].cb_data.interface =
256 		    dev->interfaces[i].desc->bInterfaceNumber;
257 
258 		dev->interfaces[i].dev->bind_cb   = devman_usb_bind_cb;
259 		dev->interfaces[i].dev->unbind_cb = devman_usb_unbind_cb;
260 		dev->interfaces[i].dev->data      = &dev->interfaces[i].cb_data;
261 
262 		/* add */
263 		res = devman_add_device(dev->interfaces[i].dev);
264 
265 		if (res != 0) {
266 			panic("devman_usb_device_add(): devman_add_device failed.");
267 		}
268 	}
269 
270 	return res;
271 }
272 
273 /****************************************************************************
274  *     devman_usb_device_remove                                             *
275  ***************************************************************************/
276 int devman_usb_device_remove(struct devman_usb_dev *dev)
277 {
278 	int i, res = 0;
279 
280 	for (i=0; i < dev->intf_count; i++) {
281 
282 		res = devman_del_device(dev->interfaces[i].dev);
283 
284 		if (res != 0) {
285 			panic("devman_usb_device_remove(): devman_del_device failed.");
286 		}
287 	}
288 	res = devman_del_device(dev->dev);
289 	return res;
290 }
291 
292 /****************************************************************************
293  *     devman_usb_init                                                      *
294  ***************************************************************************/
295 void devman_usb_init
296 (int (*_bind_cb)   (struct devman_usb_bind_cb_data *data, endpoint_t ep),
297  int (*_unbind_cb) (struct devman_usb_bind_cb_data *data, endpoint_t ep))
298 {
299 	bind_cb   = _bind_cb;
300 	unbind_cb = _unbind_cb;
301 }
302