1b3d94504SStephan Aßmus /*
2b3d94504SStephan Aßmus * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li>
3b3d94504SStephan Aßmus * Distributed under the terms of the MIT License.
4b3d94504SStephan Aßmus *
5b3d94504SStephan Aßmus */
6b3d94504SStephan Aßmus
7b3d94504SStephan Aßmus #include <KernelExport.h>
8b3d94504SStephan Aßmus #include <Drivers.h>
9b3d94504SStephan Aßmus #include <Errors.h>
10b3d94504SStephan Aßmus
11b3d94504SStephan Aßmus #include <USB.h>
12b3d94504SStephan Aßmus #include <malloc.h>
13b3d94504SStephan Aßmus #include <string.h> /* strerror */
14b3d94504SStephan Aßmus #include <stdlib.h> /* strtol */
15b3d94504SStephan Aßmus #include <stdio.h> /* sprintf */
16b3d94504SStephan Aßmus
17b3d94504SStephan Aßmus
18b3d94504SStephan Aßmus #include "usb_vision.h"
19b3d94504SStephan Aßmus #include "tracing.h"
20b3d94504SStephan Aßmus
21b3d94504SStephan Aßmus #define BASENAME_LEN 0x10 /*must be synchronized with below !!!*/
22b3d94504SStephan Aßmus static const char *basename = "video/usb_vision/%u";
23b3d94504SStephan Aßmus
24b3d94504SStephan Aßmus status_t usb_vision_device_added(const usb_device *dev, void **cookie);
25b3d94504SStephan Aßmus status_t usb_vision_device_removed(void *cookie);
26b3d94504SStephan Aßmus
27b3d94504SStephan Aßmus static usb_notify_hooks notify_hooks = {
28b3d94504SStephan Aßmus &usb_vision_device_added,
29b3d94504SStephan Aßmus &usb_vision_device_removed
30b3d94504SStephan Aßmus };
31b3d94504SStephan Aßmus
32b3d94504SStephan Aßmus struct usb_module_info *usb;
33b3d94504SStephan Aßmus usb_vision_device *usb_vision_devices[DEVICES_COUNT];
34b3d94504SStephan Aßmus char * usb_vision_names[DEVICES_COUNT + 1];
35b3d94504SStephan Aßmus sem_id usb_vision_lock = -1;
36b3d94504SStephan Aßmus
37b3d94504SStephan Aßmus struct usb_support_descriptor supported_devices[] = {
38b3d94504SStephan Aßmus {0, 0, 0, 0x0573, 0x4d31},
39b3d94504SStephan Aßmus };
40b3d94504SStephan Aßmus
41b3d94504SStephan Aßmus /* init_hardware - called once the first time the driver is loaded */
init_hardware(void)42b3d94504SStephan Aßmus status_t init_hardware (void){
43b3d94504SStephan Aßmus TRACE("init_hardware\n"); /*special case - no file-logging activated now*/
44b3d94504SStephan Aßmus return B_OK;
45b3d94504SStephan Aßmus }
46b3d94504SStephan Aßmus
47b3d94504SStephan Aßmus /* init_driver - optional function - called every time the driver is loaded. */
init_driver(void)48b3d94504SStephan Aßmus status_t init_driver (void){
49b3d94504SStephan Aßmus int i;
50b3d94504SStephan Aßmus status_t status = B_OK;
51b3d94504SStephan Aßmus load_setting();
52b3d94504SStephan Aßmus create_log();
53b3d94504SStephan Aßmus
54b3d94504SStephan Aßmus TRACE_FUNCALLS("init_driver\n");
55b3d94504SStephan Aßmus
56b3d94504SStephan Aßmus if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb)) == B_OK){
57b3d94504SStephan Aßmus if(usb){
58b3d94504SStephan Aßmus for(i = 0; i < DEVICES_COUNT; i++)
59b3d94504SStephan Aßmus usb_vision_devices[i] = 0;
60b3d94504SStephan Aßmus
61b3d94504SStephan Aßmus usb_vision_names[0] = NULL;
62b3d94504SStephan Aßmus
63*57bc6503SAlexander von Gluck IV (*usb->register_driver)(DRIVER_NAME, supported_devices, B_COUNT_OF(supported_devices), DRIVER_NAME);
64b3d94504SStephan Aßmus (*usb->install_notify)(DRIVER_NAME, ¬ify_hooks);
65b3d94504SStephan Aßmus
66b3d94504SStephan Aßmus usb_vision_lock = create_sem(1, DRIVER_NAME"_devices_table_lock");
67b3d94504SStephan Aßmus }else{
68b3d94504SStephan Aßmus status = B_ERROR;
69b3d94504SStephan Aßmus TRACE_ALWAYS("init_driver failed: usb:%08x", usb);
70b3d94504SStephan Aßmus }
71b3d94504SStephan Aßmus }else
72b3d94504SStephan Aßmus TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, B_USB_MODULE_NAME);
73b3d94504SStephan Aßmus
74b3d94504SStephan Aßmus TRACE_FUNCRET("init_driver returns:%08x\n", status);
75b3d94504SStephan Aßmus return status;
76b3d94504SStephan Aßmus }
77b3d94504SStephan Aßmus
78b3d94504SStephan Aßmus
79b3d94504SStephan Aßmus /* uninit_driver - optional function - called every time the driver is unloaded */
uninit_driver(void)80b3d94504SStephan Aßmus void uninit_driver (void){
81b3d94504SStephan Aßmus int i;
82b3d94504SStephan Aßmus TRACE_FUNCALLS("uninit_driver\n");
83b3d94504SStephan Aßmus
84b3d94504SStephan Aßmus (*usb->uninstall_notify)(DRIVER_NAME);
85b3d94504SStephan Aßmus acquire_sem(usb_vision_lock);
86b3d94504SStephan Aßmus
87b3d94504SStephan Aßmus for(i = 0; i < DEVICES_COUNT; i++)
88b3d94504SStephan Aßmus if(usb_vision_devices[i]){
89b3d94504SStephan Aßmus free(usb_vision_devices[i]);
90b3d94504SStephan Aßmus usb_vision_devices[i] = 0;
91b3d94504SStephan Aßmus }
92b3d94504SStephan Aßmus
93b3d94504SStephan Aßmus release_sem_etc(usb_vision_lock, 1, B_DO_NOT_RESCHEDULE);
94b3d94504SStephan Aßmus delete_sem(usb_vision_lock);
95b3d94504SStephan Aßmus
96b3d94504SStephan Aßmus for(i = 0; usb_vision_names[i]; i++)
97b3d94504SStephan Aßmus free(usb_vision_names[i]);
98b3d94504SStephan Aßmus
99b3d94504SStephan Aßmus put_module(B_USB_MODULE_NAME);
100b3d94504SStephan Aßmus }
101b3d94504SStephan Aßmus
102b3d94504SStephan Aßmus
103b3d94504SStephan Aßmus /* usb_vision_open - handle open() calls */
104b3d94504SStephan Aßmus
usb_vision_open(const char * name,uint32 flags,void ** cookie)105b3d94504SStephan Aßmus static status_t usb_vision_open (const char *name, uint32 flags, void** cookie)
106b3d94504SStephan Aßmus {
107b3d94504SStephan Aßmus int i;
108b3d94504SStephan Aßmus status_t status = ENODEV;
109b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_open:%s flags:%d cookie:%08x\n", name, flags, cookie);
110b3d94504SStephan Aßmus
111b3d94504SStephan Aßmus for(i = 0; i < DEVICES_COUNT; i++)
112b3d94504SStephan Aßmus TRACE("%08x\n", usb_vision_devices[i]);
113b3d94504SStephan Aßmus
114b3d94504SStephan Aßmus *cookie = NULL;
115b3d94504SStephan Aßmus i = strtol(name + BASENAME_LEN, NULL, 10);
116b3d94504SStephan Aßmus if(i >= 0 && i < DEVICES_COUNT){
117b3d94504SStephan Aßmus acquire_sem(usb_vision_lock);
118b3d94504SStephan Aßmus if(usb_vision_devices[i]){
119b3d94504SStephan Aßmus if(atomic_add(&usb_vision_devices[i]->open_count, 1) == 0){
120b3d94504SStephan Aßmus *cookie = usb_vision_devices[i];
121b3d94504SStephan Aßmus TRACE("cookie in open:%08x\n", *cookie);
122b3d94504SStephan Aßmus status = B_OK;
123b3d94504SStephan Aßmus }else{
124b3d94504SStephan Aßmus atomic_add(&usb_vision_devices[i]->open_count, -1);
125b3d94504SStephan Aßmus status = B_BUSY;
126b3d94504SStephan Aßmus }
127b3d94504SStephan Aßmus }
128b3d94504SStephan Aßmus release_sem(usb_vision_lock);
129b3d94504SStephan Aßmus }
130b3d94504SStephan Aßmus
131b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_open returns:%08x\n", status);
132b3d94504SStephan Aßmus return status;
133b3d94504SStephan Aßmus }
134b3d94504SStephan Aßmus
135b3d94504SStephan Aßmus /* usb_vision_read - handle read() calls */
136b3d94504SStephan Aßmus
usb_vision_read(void * cookie,off_t position,void * buf,size_t * num_bytes)137b3d94504SStephan Aßmus static status_t usb_vision_read (void* cookie, off_t position, void *buf, size_t* num_bytes)
138b3d94504SStephan Aßmus {
139b3d94504SStephan Aßmus *num_bytes = 0; /* tell caller nothing was read */
140b3d94504SStephan Aßmus return B_IO_ERROR;
141b3d94504SStephan Aßmus }
142b3d94504SStephan Aßmus
143b3d94504SStephan Aßmus
144b3d94504SStephan Aßmus /* usb_vision_write - handle write() calls */
145b3d94504SStephan Aßmus
usb_vision_write(void * cookie,off_t position,const void * buffer,size_t * num_bytes)146b3d94504SStephan Aßmus static status_t usb_vision_write (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
147b3d94504SStephan Aßmus {
148b3d94504SStephan Aßmus *num_bytes = 0; /* tell caller nothing was written */
149b3d94504SStephan Aßmus return B_IO_ERROR;
150b3d94504SStephan Aßmus }
151b3d94504SStephan Aßmus
xet_nt_register(bool is_read,usb_vision_device * uvd,xet_nt100x_reg * ri)152b3d94504SStephan Aßmus static status_t xet_nt_register(bool is_read, usb_vision_device *uvd, xet_nt100x_reg *ri)
153b3d94504SStephan Aßmus {
154b3d94504SStephan Aßmus status_t status = B_ERROR;
1551ad7e244SFrançois Revol //uint8 req_type = USB_REQTYPE_VENDOR | (is_read ? USB_REQTYPE_DEVICE_IN : USB_REQTYPE_DEVICE_OUT);
156b3d94504SStephan Aßmus
157b3d94504SStephan Aßmus TRACE_FUNCALLS("set_nt_register:%08x, %08x\n", uvd, ri);
158b3d94504SStephan Aßmus TRACE_FUNCRES(trace_reginfo, ri);
159b3d94504SStephan Aßmus
160b3d94504SStephan Aßmus //(*usb->send_request)(uvd->dev, req_type,
161b3d94504SStephan Aßmus // )
162b3d94504SStephan Aßmus
163b3d94504SStephan Aßmus TRACE_FUNCRET("set_nt_register returns:%08x\n", status);
164b3d94504SStephan Aßmus return status;
165b3d94504SStephan Aßmus }
166b3d94504SStephan Aßmus
167b3d94504SStephan Aßmus /* usb_vision_control - handle ioctl calls */
usb_vision_control(void * cookie,uint32 op,void * arg,size_t len)168b3d94504SStephan Aßmus static status_t usb_vision_control (void* cookie, uint32 op, void* arg, size_t len)
169b3d94504SStephan Aßmus {
170b3d94504SStephan Aßmus status_t status = B_BAD_VALUE;
171b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_control:%08x, %d, %08x, %d\n", cookie, op, arg, len);
172b3d94504SStephan Aßmus switch(op){
173b3d94504SStephan Aßmus case NT_IOCTL_READ_REGISTER:
174b3d94504SStephan Aßmus status = xet_nt_register(true, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
175b3d94504SStephan Aßmus break;
176b3d94504SStephan Aßmus case NT_IOCTL_WRITE_REGISTER:
177b3d94504SStephan Aßmus status = xet_nt_register(false, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
178b3d94504SStephan Aßmus break;
179b3d94504SStephan Aßmus default:
180b3d94504SStephan Aßmus break;
181b3d94504SStephan Aßmus }
182b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_control returns:%08x\n", status);
183b3d94504SStephan Aßmus return status;
184b3d94504SStephan Aßmus }
185b3d94504SStephan Aßmus
186b3d94504SStephan Aßmus /* usb_vision_close - handle close() calls */
usb_vision_close(void * cookie)187b3d94504SStephan Aßmus static status_t usb_vision_close (void* cookie)
188b3d94504SStephan Aßmus {
189b3d94504SStephan Aßmus status_t status = B_OK;//ENODEV;
190b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_close:%08x\n", cookie);
191b3d94504SStephan Aßmus
192b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_close returns:%08x\n", status);
193b3d94504SStephan Aßmus return status;
194b3d94504SStephan Aßmus }
195b3d94504SStephan Aßmus
196b3d94504SStephan Aßmus
197b3d94504SStephan Aßmus /* usb_vision_free - called after the last device is closed, and after all i/o is complete. */
usb_vision_free(void * cookie)198b3d94504SStephan Aßmus static status_t usb_vision_free (void* cookie)
199b3d94504SStephan Aßmus {
200b3d94504SStephan Aßmus status_t status = B_OK;
201b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_free:%08x\n", cookie);
202b3d94504SStephan Aßmus
203b3d94504SStephan Aßmus if(cookie){
204b3d94504SStephan Aßmus usb_vision_device *uvd = (usb_vision_device *)cookie;
205b3d94504SStephan Aßmus atomic_add(&uvd->open_count, -1);
206b3d94504SStephan Aßmus }
207b3d94504SStephan Aßmus
208b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_free returns:%08x\n", status);
209b3d94504SStephan Aßmus return status;
210b3d94504SStephan Aßmus }
211b3d94504SStephan Aßmus
212b3d94504SStephan Aßmus /* function pointers for the device hooks entry points */
213b3d94504SStephan Aßmus device_hooks usb_vision_hooks = {
214b3d94504SStephan Aßmus usb_vision_open, /* -> open entry point */
215b3d94504SStephan Aßmus usb_vision_close, /* -> close entry point */
216b3d94504SStephan Aßmus usb_vision_free, /* -> free cookie */
217b3d94504SStephan Aßmus usb_vision_control, /* -> control entry point */
218b3d94504SStephan Aßmus usb_vision_read, /* -> read entry point */
219b3d94504SStephan Aßmus usb_vision_write /* -> write entry point */
220b3d94504SStephan Aßmus };
221b3d94504SStephan Aßmus
222b3d94504SStephan Aßmus /* publish_devices - return a null-terminated array of devices
223b3d94504SStephan Aßmus supported by this driver. */
224b3d94504SStephan Aßmus
publish_devices()225b3d94504SStephan Aßmus const char** publish_devices(){
226b3d94504SStephan Aßmus int i, j;
227b3d94504SStephan Aßmus TRACE_FUNCALLS("publish_devices\n");
228b3d94504SStephan Aßmus
229b3d94504SStephan Aßmus for(i=0; usb_vision_names[i]; i++)
230b3d94504SStephan Aßmus free(usb_vision_names[i]);
231b3d94504SStephan Aßmus
232b3d94504SStephan Aßmus acquire_sem(usb_vision_lock);
233b3d94504SStephan Aßmus for(i=0, j=0; i < DEVICES_COUNT; i++){
234b3d94504SStephan Aßmus if(usb_vision_devices[i]){
235b3d94504SStephan Aßmus usb_vision_names[j] = malloc(strlen(basename + 2));
236b3d94504SStephan Aßmus if(usb_vision_names[j]){
237b3d94504SStephan Aßmus sprintf(usb_vision_names[j], basename, i);
238b3d94504SStephan Aßmus j++;
239b3d94504SStephan Aßmus }
240b3d94504SStephan Aßmus else
241b3d94504SStephan Aßmus TRACE_ALWAYS("publish_devices - NO MEMORY\n");
242b3d94504SStephan Aßmus }
243b3d94504SStephan Aßmus }
244b3d94504SStephan Aßmus usb_vision_names[j] = NULL;
245b3d94504SStephan Aßmus release_sem(usb_vision_lock);
246b3d94504SStephan Aßmus
247b3d94504SStephan Aßmus return (const char **)&usb_vision_names[0];
248b3d94504SStephan Aßmus }
249b3d94504SStephan Aßmus
250b3d94504SStephan Aßmus /* find_device - return ptr to device hooks structure for a
251b3d94504SStephan Aßmus given device name */
find_device(const char * name)252b3d94504SStephan Aßmus device_hooks* find_device(const char* name){
253b3d94504SStephan Aßmus TRACE_FUNCALLS("find_device(%s)\n", name);
254b3d94504SStephan Aßmus return &usb_vision_hooks;
255b3d94504SStephan Aßmus }
256b3d94504SStephan Aßmus
create_add_device(usb_vision_device * uvd,const struct usb_configuration_info * uci,struct usb_endpoint_info * control_epi,struct usb_endpoint_info * data_epi)2571ad7e244SFrançois Revol static status_t create_add_device(usb_vision_device *uvd, const struct usb_configuration_info *uci,
258b3d94504SStephan Aßmus struct usb_endpoint_info *control_epi,
259b3d94504SStephan Aßmus struct usb_endpoint_info *data_epi){
260b3d94504SStephan Aßmus // char name[32];
261b3d94504SStephan Aßmus status_t status = ENODEV;
262b3d94504SStephan Aßmus // size_t buf_len;
263b3d94504SStephan Aßmus int i = 0;
264b3d94504SStephan Aßmus
265b3d94504SStephan Aßmus TRACE_FUNCALLS("create_add_device(%08x, %08x, %08x, %08x)\n", uvd, uci, control_epi, data_epi);
266b3d94504SStephan Aßmus
267b3d94504SStephan Aßmus acquire_sem(usb_vision_lock);
268b3d94504SStephan Aßmus
269b3d94504SStephan Aßmus for(i = 0; i < DEVICES_COUNT; i++){
270b3d94504SStephan Aßmus if(usb_vision_devices[i] != NULL)
271b3d94504SStephan Aßmus continue;
272b3d94504SStephan Aßmus
273b3d94504SStephan Aßmus usb_vision_devices[i] = uvd;
274b3d94504SStephan Aßmus /*
275b3d94504SStephan Aßmus usd->active = 1;
276b3d94504SStephan Aßmus usd->open = 0;
277b3d94504SStephan Aßmus
278b3d94504SStephan Aßmus sprintf(name, "usb_vision:%d:done_read", i );
279b3d94504SStephan Aßmus usd->done_read = create_sem(0, name);
280b3d94504SStephan Aßmus
281b3d94504SStephan Aßmus sprintf(name, "usb_vision:%d:done_write", i);
282b3d94504SStephan Aßmus usd->done_write = create_sem(0, name);
283b3d94504SStephan Aßmus
284b3d94504SStephan Aßmus usd->tty = NULL;
285b3d94504SStephan Aßmus
286b3d94504SStephan Aßmus buf_len = usd->read_buffer_size + usd->write_buffer_size + usd->interrupt_buffer_size;
287b3d94504SStephan Aßmus
288b3d94504SStephan Aßmus usd->buffers_area = create_area("usb_serial:buffers_area", (void *)&usd->read_buffer, B_ANY_KERNEL_ADDRESS,
289b3d94504SStephan Aßmus ROUNDUP(buf_len, B_PAGE_SIZE),
290b3d94504SStephan Aßmus B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA);
291b3d94504SStephan Aßmus
292b3d94504SStephan Aßmus usd->write_buffer = usd->read_buffer + usd->read_buffer_size;
293b3d94504SStephan Aßmus usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size;
294b3d94504SStephan Aßmus */
295b3d94504SStephan Aßmus (*usb->set_configuration)(uvd->dev, uci);
296b3d94504SStephan Aßmus
297b3d94504SStephan Aßmus uvd->control_pipe = control_epi->handle;
298b3d94504SStephan Aßmus uvd->data_pipe = data_epi->handle;
299b3d94504SStephan Aßmus
300b3d94504SStephan Aßmus status = B_OK;
301b3d94504SStephan Aßmus break;
302b3d94504SStephan Aßmus }
303b3d94504SStephan Aßmus release_sem(usb_vision_lock);
304b3d94504SStephan Aßmus
305b3d94504SStephan Aßmus TRACE_FUNCRET("add_device returns:%08x\n", status);
306b3d94504SStephan Aßmus return status;
307b3d94504SStephan Aßmus }
308b3d94504SStephan Aßmus
add_device(usb_vision_device * uvd,const usb_configuration_info * uci)3091ad7e244SFrançois Revol static status_t add_device(usb_vision_device *uvd, const usb_configuration_info *uci){
310b3d94504SStephan Aßmus usb_endpoint_info *control_epi = NULL;
311b3d94504SStephan Aßmus usb_endpoint_info *data_epi = NULL;
312b3d94504SStephan Aßmus status_t status = ENODEV;
313b3d94504SStephan Aßmus int i = 0;
314b3d94504SStephan Aßmus usb_interface_info *uii = uci->interface[0].active;
315b3d94504SStephan Aßmus TRACE_FUNCALLS("> add_device(%08x, %08x)\n", uvd, uci);
316b3d94504SStephan Aßmus
317b3d94504SStephan Aßmus for(i=0; i < uii->endpoint_count; i++){
318b3d94504SStephan Aßmus if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_ISOCHRONOUS){
319b3d94504SStephan Aßmus if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) == USB_EP_ADDR_DIR_IN){
320b3d94504SStephan Aßmus data_epi = &uii->endpoint[i];
321b3d94504SStephan Aßmus TRACE("iso_ep:%d\n", i);
322b3d94504SStephan Aßmus }
323b3d94504SStephan Aßmus }
324b3d94504SStephan Aßmus if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_CONTROL){
325b3d94504SStephan Aßmus control_epi = &uii->endpoint[i];
326b3d94504SStephan Aßmus TRACE("cont_ep:%d\n", i);
327b3d94504SStephan Aßmus }
328b3d94504SStephan Aßmus if(control_epi && data_epi)
329b3d94504SStephan Aßmus break;
330b3d94504SStephan Aßmus }
331b3d94504SStephan Aßmus
332b3d94504SStephan Aßmus if(control_epi && data_epi){
333b3d94504SStephan Aßmus status = create_add_device(uvd, uci, control_epi, data_epi);
334b3d94504SStephan Aßmus }
335b3d94504SStephan Aßmus
336b3d94504SStephan Aßmus TRACE_FUNCRET("< create_add_device returns:%08x\n", status);
337b3d94504SStephan Aßmus return status;
338b3d94504SStephan Aßmus }
339b3d94504SStephan Aßmus
usb_vision_device_added(const usb_device * dev,void ** cookie)340b3d94504SStephan Aßmus status_t usb_vision_device_added(const usb_device *dev, void **cookie){
341b3d94504SStephan Aßmus int dev_idx;
342b3d94504SStephan Aßmus status_t status = B_OK;
343b3d94504SStephan Aßmus const usb_device_descriptor *udd;
344b3d94504SStephan Aßmus usb_vision_device *uvd = 0;
345b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_device_added:%08x cookie:%08x\n", dev, cookie);
346b3d94504SStephan Aßmus
347b3d94504SStephan Aßmus udd = (*usb->get_device_descriptor)(dev);
348b3d94504SStephan Aßmus TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id);
349b3d94504SStephan Aßmus
350b3d94504SStephan Aßmus *cookie = 0;
351*57bc6503SAlexander von Gluck IV for(dev_idx = 0; dev_idx < B_COUNT_OF(supported_devices); dev_idx++)
352b3d94504SStephan Aßmus if(supported_devices[dev_idx].vendor == udd->vendor_id
353b3d94504SStephan Aßmus && supported_devices[dev_idx].product == udd->product_id){
354b3d94504SStephan Aßmus const usb_configuration_info *uci;
355b3d94504SStephan Aßmus int cfg_idx;
356b3d94504SStephan Aßmus for(cfg_idx = 0; (uci = (*usb->get_nth_configuration)(dev, cfg_idx)) != NULL; cfg_idx++){
357b3d94504SStephan Aßmus uvd = malloc(sizeof(usb_vision_device));
358b3d94504SStephan Aßmus if(uvd){
359b3d94504SStephan Aßmus memset(uvd, 0, sizeof(usb_vision_device));
360b3d94504SStephan Aßmus uvd->dev = dev;
361b3d94504SStephan Aßmus if((status = add_device(uvd, uci)) == B_OK){
3621ad7e244SFrançois Revol *cookie = (void *)dev;
363b3d94504SStephan Aßmus TRACE_ALWAYS("(%04x/%04x) added \n", supported_devices[dev_idx].vendor,
364b3d94504SStephan Aßmus supported_devices[dev_idx].product);
365b3d94504SStephan Aßmus break;
366b3d94504SStephan Aßmus }else
367b3d94504SStephan Aßmus free(uvd);
368b3d94504SStephan Aßmus }else
369b3d94504SStephan Aßmus status = B_NO_MEMORY;
370b3d94504SStephan Aßmus }
371b3d94504SStephan Aßmus break;
372b3d94504SStephan Aßmus }
373b3d94504SStephan Aßmus
374b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_device_added returns:%08x\n", status);
375b3d94504SStephan Aßmus return status;
376b3d94504SStephan Aßmus }
377b3d94504SStephan Aßmus
usb_vision_device_removed(void * cookie)378b3d94504SStephan Aßmus status_t usb_vision_device_removed(void *cookie){
379b3d94504SStephan Aßmus int i;
380b3d94504SStephan Aßmus status_t status = B_OK;
381b3d94504SStephan Aßmus struct usb_device *ud = (struct usb_device *) cookie;
382b3d94504SStephan Aßmus TRACE_FUNCALLS("usb_vision_device_removed:%08x\n", cookie);
383b3d94504SStephan Aßmus
384b3d94504SStephan Aßmus acquire_sem(usb_vision_lock);
385b3d94504SStephan Aßmus
386b3d94504SStephan Aßmus for(i = 0; i < DEVICES_COUNT; i++ ){
387b3d94504SStephan Aßmus usb_vision_device *uvd = usb_vision_devices[i];
388b3d94504SStephan Aßmus if(uvd){
389b3d94504SStephan Aßmus if(ud == uvd->dev){
390b3d94504SStephan Aßmus free(uvd);
391b3d94504SStephan Aßmus usb_vision_devices[i] = 0;
392b3d94504SStephan Aßmus }
393b3d94504SStephan Aßmus }
394b3d94504SStephan Aßmus }
395b3d94504SStephan Aßmus
396b3d94504SStephan Aßmus release_sem(usb_vision_lock);
397b3d94504SStephan Aßmus
398b3d94504SStephan Aßmus TRACE_FUNCRET("usb_vision_device_removed returns:%08x\n", status);
399b3d94504SStephan Aßmus return status;
400b3d94504SStephan Aßmus }
401