2 * Copyright (c) 2003 by Siarzhuk Zharski <imker@gmx.li>
3 * Distributed under the terms of the MIT License.
7 #include <KernelExport.h>
13 #include <string.h> /* strerror */
14 #include <stdlib.h> /* strtol */
15 #include <stdio.h> /* sprintf */
18 #include "usb_vision.h"
21 #define BASENAME_LEN 0x10 /*must be synchronized with below !!!*/
22 static const char *basename
= "video/usb_vision/%u";
24 status_t
usb_vision_device_added(const usb_device
*dev
, void **cookie
);
25 status_t
usb_vision_device_removed(void *cookie
);
27 static usb_notify_hooks notify_hooks
= {
28 &usb_vision_device_added
,
29 &usb_vision_device_removed
32 struct usb_module_info
*usb
;
33 usb_vision_device
*usb_vision_devices
[DEVICES_COUNT
];
34 char * usb_vision_names
[DEVICES_COUNT
+ 1];
35 sem_id usb_vision_lock
= -1;
37 struct usb_support_descriptor supported_devices
[] = {
38 {0, 0, 0, 0x0573, 0x4d31},
41 /* init_hardware - called once the first time the driver is loaded */
42 status_t
init_hardware (void){
43 TRACE("init_hardware\n"); /*special case - no file-logging activated now*/
47 /* init_driver - optional function - called every time the driver is loaded. */
48 status_t
init_driver (void){
50 status_t status
= B_OK
;
54 TRACE_FUNCALLS("init_driver\n");
56 if((status
= get_module(B_USB_MODULE_NAME
, (module_info
**)&usb
)) == B_OK
){
58 for(i
= 0; i
< DEVICES_COUNT
; i
++)
59 usb_vision_devices
[i
] = 0;
61 usb_vision_names
[0] = NULL
;
63 (*usb
->register_driver
)(DRIVER_NAME
, supported_devices
, B_COUNT_OF(supported_devices
), DRIVER_NAME
);
64 (*usb
->install_notify
)(DRIVER_NAME
, ¬ify_hooks
);
66 usb_vision_lock
= create_sem(1, DRIVER_NAME
"_devices_table_lock");
69 TRACE_ALWAYS("init_driver failed: usb:%08x", usb
);
72 TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status
, B_USB_MODULE_NAME
);
74 TRACE_FUNCRET("init_driver returns:%08x\n", status
);
79 /* uninit_driver - optional function - called every time the driver is unloaded */
80 void uninit_driver (void){
82 TRACE_FUNCALLS("uninit_driver\n");
84 (*usb
->uninstall_notify
)(DRIVER_NAME
);
85 acquire_sem(usb_vision_lock
);
87 for(i
= 0; i
< DEVICES_COUNT
; i
++)
88 if(usb_vision_devices
[i
]){
89 free(usb_vision_devices
[i
]);
90 usb_vision_devices
[i
] = 0;
93 release_sem_etc(usb_vision_lock
, 1, B_DO_NOT_RESCHEDULE
);
94 delete_sem(usb_vision_lock
);
96 for(i
= 0; usb_vision_names
[i
]; i
++)
97 free(usb_vision_names
[i
]);
99 put_module(B_USB_MODULE_NAME
);
103 /* usb_vision_open - handle open() calls */
105 static status_t
usb_vision_open (const char *name
, uint32 flags
, void** cookie
)
108 status_t status
= ENODEV
;
109 TRACE_FUNCALLS("usb_vision_open:%s flags:%d cookie:%08x\n", name
, flags
, cookie
);
111 for(i
= 0; i
< DEVICES_COUNT
; i
++)
112 TRACE("%08x\n", usb_vision_devices
[i
]);
115 i
= strtol(name
+ BASENAME_LEN
, NULL
, 10);
116 if(i
>= 0 && i
< DEVICES_COUNT
){
117 acquire_sem(usb_vision_lock
);
118 if(usb_vision_devices
[i
]){
119 if(atomic_add(&usb_vision_devices
[i
]->open_count
, 1) == 0){
120 *cookie
= usb_vision_devices
[i
];
121 TRACE("cookie in open:%08x\n", *cookie
);
124 atomic_add(&usb_vision_devices
[i
]->open_count
, -1);
128 release_sem(usb_vision_lock
);
131 TRACE_FUNCRET("usb_vision_open returns:%08x\n", status
);
135 /* usb_vision_read - handle read() calls */
137 static status_t
usb_vision_read (void* cookie
, off_t position
, void *buf
, size_t* num_bytes
)
139 *num_bytes
= 0; /* tell caller nothing was read */
144 /* usb_vision_write - handle write() calls */
146 static status_t
usb_vision_write (void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
)
148 *num_bytes
= 0; /* tell caller nothing was written */
152 static status_t
xet_nt_register(bool is_read
, usb_vision_device
*uvd
, xet_nt100x_reg
*ri
)
154 status_t status
= B_ERROR
;
155 //uint8 req_type = USB_REQTYPE_VENDOR | (is_read ? USB_REQTYPE_DEVICE_IN : USB_REQTYPE_DEVICE_OUT);
157 TRACE_FUNCALLS("set_nt_register:%08x, %08x\n", uvd
, ri
);
158 TRACE_FUNCRES(trace_reginfo
, ri
);
160 //(*usb->send_request)(uvd->dev, req_type,
163 TRACE_FUNCRET("set_nt_register returns:%08x\n", status
);
167 /* usb_vision_control - handle ioctl calls */
168 static status_t
usb_vision_control (void* cookie
, uint32 op
, void* arg
, size_t len
)
170 status_t status
= B_BAD_VALUE
;
171 TRACE_FUNCALLS("usb_vision_control:%08x, %d, %08x, %d\n", cookie
, op
, arg
, len
);
173 case NT_IOCTL_READ_REGISTER
:
174 status
= xet_nt_register(true, (usb_vision_device
*)cookie
, (xet_nt100x_reg
*) arg
);
176 case NT_IOCTL_WRITE_REGISTER
:
177 status
= xet_nt_register(false, (usb_vision_device
*)cookie
, (xet_nt100x_reg
*) arg
);
182 TRACE_FUNCRET("usb_vision_control returns:%08x\n", status
);
186 /* usb_vision_close - handle close() calls */
187 static status_t
usb_vision_close (void* cookie
)
189 status_t status
= B_OK
;//ENODEV;
190 TRACE_FUNCALLS("usb_vision_close:%08x\n", cookie
);
192 TRACE_FUNCRET("usb_vision_close returns:%08x\n", status
);
197 /* usb_vision_free - called after the last device is closed, and after all i/o is complete. */
198 static status_t
usb_vision_free (void* cookie
)
200 status_t status
= B_OK
;
201 TRACE_FUNCALLS("usb_vision_free:%08x\n", cookie
);
204 usb_vision_device
*uvd
= (usb_vision_device
*)cookie
;
205 atomic_add(&uvd
->open_count
, -1);
208 TRACE_FUNCRET("usb_vision_free returns:%08x\n", status
);
212 /* function pointers for the device hooks entry points */
213 device_hooks usb_vision_hooks
= {
214 usb_vision_open
, /* -> open entry point */
215 usb_vision_close
, /* -> close entry point */
216 usb_vision_free
, /* -> free cookie */
217 usb_vision_control
, /* -> control entry point */
218 usb_vision_read
, /* -> read entry point */
219 usb_vision_write
/* -> write entry point */
222 /* publish_devices - return a null-terminated array of devices
223 supported by this driver. */
225 const char** publish_devices(){
227 TRACE_FUNCALLS("publish_devices\n");
229 for(i
=0; usb_vision_names
[i
]; i
++)
230 free(usb_vision_names
[i
]);
232 acquire_sem(usb_vision_lock
);
233 for(i
=0, j
=0; i
< DEVICES_COUNT
; i
++){
234 if(usb_vision_devices
[i
]){
235 usb_vision_names
[j
] = malloc(strlen(basename
+ 2));
236 if(usb_vision_names
[j
]){
237 sprintf(usb_vision_names
[j
], basename
, i
);
241 TRACE_ALWAYS("publish_devices - NO MEMORY\n");
244 usb_vision_names
[j
] = NULL
;
245 release_sem(usb_vision_lock
);
247 return (const char **)&usb_vision_names
[0];
250 /* find_device - return ptr to device hooks structure for a
252 device_hooks
* find_device(const char* name
){
253 TRACE_FUNCALLS("find_device(%s)\n", name
);
254 return &usb_vision_hooks
;
257 static status_t
create_add_device(usb_vision_device
*uvd
, const struct usb_configuration_info
*uci
,
258 struct usb_endpoint_info
*control_epi
,
259 struct usb_endpoint_info
*data_epi
){
261 status_t status
= ENODEV
;
265 TRACE_FUNCALLS("create_add_device(%08x, %08x, %08x, %08x)\n", uvd
, uci
, control_epi
, data_epi
);
267 acquire_sem(usb_vision_lock
);
269 for(i
= 0; i
< DEVICES_COUNT
; i
++){
270 if(usb_vision_devices
[i
] != NULL
)
273 usb_vision_devices
[i
] = uvd
;
278 sprintf(name, "usb_vision:%d:done_read", i );
279 usd->done_read = create_sem(0, name);
281 sprintf(name, "usb_vision:%d:done_write", i);
282 usd->done_write = create_sem(0, name);
286 buf_len = usd->read_buffer_size + usd->write_buffer_size + usd->interrupt_buffer_size;
288 usd->buffers_area = create_area("usb_serial:buffers_area", (void *)&usd->read_buffer, B_ANY_KERNEL_ADDRESS,
289 ROUNDUP(buf_len, B_PAGE_SIZE),
290 B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA);
292 usd->write_buffer = usd->read_buffer + usd->read_buffer_size;
293 usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size;
295 (*usb
->set_configuration
)(uvd
->dev
, uci
);
297 uvd
->control_pipe
= control_epi
->handle
;
298 uvd
->data_pipe
= data_epi
->handle
;
303 release_sem(usb_vision_lock
);
305 TRACE_FUNCRET("add_device returns:%08x\n", status
);
309 static status_t
add_device(usb_vision_device
*uvd
, const usb_configuration_info
*uci
){
310 usb_endpoint_info
*control_epi
= NULL
;
311 usb_endpoint_info
*data_epi
= NULL
;
312 status_t status
= ENODEV
;
314 usb_interface_info
*uii
= uci
->interface
[0].active
;
315 TRACE_FUNCALLS("> add_device(%08x, %08x)\n", uvd
, uci
);
317 for(i
=0; i
< uii
->endpoint_count
; i
++){
318 if(uii
->endpoint
[i
].descr
->attributes
== USB_EP_ATTR_ISOCHRONOUS
){
319 if((uii
->endpoint
[i
].descr
->endpoint_address
& USB_EP_ADDR_DIR_IN
) == USB_EP_ADDR_DIR_IN
){
320 data_epi
= &uii
->endpoint
[i
];
321 TRACE("iso_ep:%d\n", i
);
324 if(uii
->endpoint
[i
].descr
->attributes
== USB_EP_ATTR_CONTROL
){
325 control_epi
= &uii
->endpoint
[i
];
326 TRACE("cont_ep:%d\n", i
);
328 if(control_epi
&& data_epi
)
332 if(control_epi
&& data_epi
){
333 status
= create_add_device(uvd
, uci
, control_epi
, data_epi
);
336 TRACE_FUNCRET("< create_add_device returns:%08x\n", status
);
340 status_t
usb_vision_device_added(const usb_device
*dev
, void **cookie
){
342 status_t status
= B_OK
;
343 const usb_device_descriptor
*udd
;
344 usb_vision_device
*uvd
= 0;
345 TRACE_FUNCALLS("usb_vision_device_added:%08x cookie:%08x\n", dev
, cookie
);
347 udd
= (*usb
->get_device_descriptor
)(dev
);
348 TRACE_ALWAYS("Probing device: %08x/%08x\n", udd
->vendor_id
, udd
->product_id
);
351 for(dev_idx
= 0; dev_idx
< B_COUNT_OF(supported_devices
); dev_idx
++)
352 if(supported_devices
[dev_idx
].vendor
== udd
->vendor_id
353 && supported_devices
[dev_idx
].product
== udd
->product_id
){
354 const usb_configuration_info
*uci
;
356 for(cfg_idx
= 0; (uci
= (*usb
->get_nth_configuration
)(dev
, cfg_idx
)) != NULL
; cfg_idx
++){
357 uvd
= malloc(sizeof(usb_vision_device
));
359 memset(uvd
, 0, sizeof(usb_vision_device
));
361 if((status
= add_device(uvd
, uci
)) == B_OK
){
362 *cookie
= (void *)dev
;
363 TRACE_ALWAYS("(%04x/%04x) added \n", supported_devices
[dev_idx
].vendor
,
364 supported_devices
[dev_idx
].product
);
369 status
= B_NO_MEMORY
;
374 TRACE_FUNCRET("usb_vision_device_added returns:%08x\n", status
);
378 status_t
usb_vision_device_removed(void *cookie
){
380 status_t status
= B_OK
;
381 struct usb_device
*ud
= (struct usb_device
*) cookie
;
382 TRACE_FUNCALLS("usb_vision_device_removed:%08x\n", cookie
);
384 acquire_sem(usb_vision_lock
);
386 for(i
= 0; i
< DEVICES_COUNT
; i
++ ){
387 usb_vision_device
*uvd
= usb_vision_devices
[i
];
391 usb_vision_devices
[i
] = 0;
396 release_sem(usb_vision_lock
);
398 TRACE_FUNCRET("usb_vision_device_removed returns:%08x\n", status
);