+
+
+1. Installation
+
+2. Uninstallation
+
+
+3. Problems solving
+
+- If this driver crash your system - reboot and press "Space" during load. In boot menu select
+ "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode.
+ Write me a e-mail about this problem.
+
+4. "Unknown" devices
+
+ If you have something, that looks like USB->RS232(serial) adapter or USB modem and tried it with
+ this driver but have no success - download
+ usb device info tool and use it to get required information.
+
+- Unplug all USB devices and hubs from your PC.
+
- Go into Terminal and run the following command:
+ ls -alR /dev/bus/usb
+ You should see something like this:
+
+$ ls -alR /dev/bus/usb/
+/dev/bus/usb:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 Jun 1 2003 ..
+drw-r--r-- 1 walther users 0 May 31 23:16 0
+drw-r--r-- 1 walther users 0 May 31 23:16 1
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 unload
+
+/dev/bus/usb/0:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+/dev/bus/usb/1:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+
+ - Note this information.
+
- Now plug your USB serial adapter into PC and run ls -alR /dev/bus/usb/ again.
+You'll get something slightly different:
+
+$ ls -alR /dev/bus/usb/
+/dev/bus/usb:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 Jun 1 2003 ..
+drw-r--r-- 1 walther users 0 May 31 23:16 0
+drw-r--r-- 1 walther users 0 May 31 23:16 1
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 unload
+
+/dev/bus/usb/0:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+/dev/bus/usb/1:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+
+$
+ - Compare this results with previous one and look for file,
+that appeared. This file is your USB serial adapter.
+
- Unpack downloaded usb_dev_info command and run it with full path to file appeared in
+the second listing. For my sample I should run:
+usb_dev_info /dev/bus/usb/0/1
+I'll get the following:
+
+$ usb_dev_info /dev/bus/usb/0/1
+[Device]
+Class .................. 0
+Subclass ............... 0
+Protocol ............... 0
+Vendor ID .............. 0x067b
+Product ID ............. 0x2303
+Version ................ 0x0202
+Manufacturer String .... ""
+Product String ......... ""
+Serial Number .......... ""
+ [Configuration 0]
+ [Interface 0]
+ Class .............. 255
+ Subclass ........... 0
+ Protocol ........... 0
+ [Endpoint 0]
+ MaxPacketSize .... 10
+ Interval ......... 1
+ Type ............. Interrupt
+ Direction ........ Input
+ [Endpoint 1]
+ MaxPacketSize .... 64
+ Interval ......... 0
+ Type ............. Bulk
+ Direction ........ Output
+ [Endpoint 2]
+ MaxPacketSize .... 64
+ Interval ......... 0
+ Type ............. Bulk
+ Direction ........ Input
+
+ - Send this information to me with some additional words about your device.
+
+
+What is wrong with BeOS.USB.patches?
+
+All know that "classical" BeOS R5 don't works on OHCI USB hardware. But some time ago on one well-known
+BeOS file-sharing network appeared patches for plain R5. Those patches allows to work with OHCI
+hardware under this system version. Looks like it is some part of Dan0 or other "leaked" versions.
+There are 3 patches in BeOS.USB.patches.zip:
+1. beos-usb-patch,
+
2. beos-usb.modem-patch,
+
3. beos-usb.modem-patch.sm.
+
The Evil is in two last patches. The source of problem - changed functions in tty module. The
+Dan0 contains two additional functions in the middle of tty module description table. But the module version
+was not changed - it is still v1. So if driver, that was compiled with old tty module layout, will try to use it - system
+crashes. Looks like those patches contains the same "enchanced" tty module like in Dan0. So - you should roll back
+those modem-patches - restore the previous configuration as described in patches readme. The first one
+- "beos-usb-patch" is OK.
+
+
Information for Dan0 users
+
+The driver is still not working under Dan0 out of box. At first you have no need to use it for ACM-compatible devices,
+because Dan0 has it's own implementation of usb_acm driver. There is also one problem with Dan0 - the
+"tty" module was chaged in very dangerous way - there is no possibility to create backward compatible
+implementation of serial port driver with the new tty interfaces. If you really have one of those USB Serial
+Adapters and want to use it under Dan0 - you have to make some hand work. Sorry for this, but I have not
+using Dan0 as my main working system. So you must to build Dan0 version by yourself. Thank you for your patience. Below
+is an operations you need to install USB serial driver for Dan0:
+
+Siarzuk Zharski
+
http://www.zharik.host.sk/
+
\ No newline at end of file
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.c b/src/add-ons/kernel/drivers/ports/usb_serial/acm.c
new file mode 100644
index 0000000000..0b2ed7432e
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/acm.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+#include "driver.h"
+#include "acm.h"
+
+status_t add_acm_device(usb_serial_device *usd,
+ const usb_configuration_info *uci)
+{
+ struct usb_endpoint_info *comm_epi = NULL;
+ struct usb_endpoint_info *data_out_epi = NULL;
+ struct usb_endpoint_info *data_in_epi = NULL;
+ status_t status = ENODEV;
+ int i = 0;
+
+ TRACE_FUNCALLS("> add_acm_device(%08x, %08x)\n", usd, uci);
+
+ for(i=0; i < uci->interface_count; i++){
+ usb_interface_descriptor *uid =
+ uci->interface[i].active->descr;
+ if(uid->interface_class == USB_INT_CLASS_CDC &&
+ uid->interface_subclass == USB_INT_SUBCLASS_ABSTRACT_CONTROL_MODEL &&
+ uid->num_endpoints == 1){
+ comm_epi = uci->interface[i].active->endpoint;
+ }
+
+ if(uid->interface_class == USB_INT_CLASS_CDC_DATA &&
+ (uid->interface_subclass == 2 || // ?????????????
+ uid->interface_subclass == USB_INT_SUBCLASS_DATA)){
+ if(uid->num_endpoints == 2){
+ data_out_epi = &uci->interface[i].active->endpoint[0];
+ data_in_epi = &uci->interface[i].active->endpoint[1];
+ }
+ }
+ if(comm_epi && data_out_epi && data_in_epi)
+ break;
+ }
+
+ if(comm_epi && data_out_epi && data_in_epi){
+ status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi);
+ }
+
+ TRACE_FUNCRET("< add_acm_device returns:%08x\n", status);
+ return status;
+}
+
+status_t reset_acm_device(usb_serial_device *usd){
+ status_t status = B_OK;
+ TRACE_FUNCALLS("> reset_acm_device(%08x)\n", usd);
+ TRACE_FUNCRET("< reset_acm_device returns:%08x\n", status);
+ return status;
+}
+
+status_t set_line_coding_acm(usb_serial_device *usd,
+ usb_serial_line_coding *line_coding){
+ size_t len = 0;
+ status_t status = B_OK;
+ TRACE_FUNCALLS("> set_line_coding_acm(%08x, {%d, %02x, %02x, %02x})\n",
+ usd, line_coding->speed,
+ line_coding->stopbits,
+ line_coding->parity,
+ line_coding->databits);
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_LINE_CODING, 0x0, 0x0,
+ sizeof(usb_serial_line_coding),
+ line_coding,
+ sizeof(usb_serial_line_coding), &len);
+ TRACE_FUNCRET("< set_line_coding_acm returns:%08x\n", status);
+ return status;
+}
+
+status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state){
+ size_t len = 0;
+ status_t status = B_OK;
+ TRACE_FUNCALLS("> set_control_line_state_acm(%08x, %04x)\n", usd, state);
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT,
+ SET_CONTROL_LINE_STATE, state, 0, 0, 0, 0,
+ &len);
+ TRACE_FUNCRET("< set_control_line_state_acm returns:%08x\n", status);
+ return status;
+}
+
+void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes){
+}
+
+void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes){
+ if(*num_bytes > usd->write_buffer_size)
+ *num_bytes = usd->write_buffer_size;
+ memcpy(usd->write_buffer, buf, *num_bytes);
+}
+
+void on_close_acm(usb_serial_device *usd){
+ TRACE_FUNCALLS("> add_acm_device(%08x)\n", usd);
+ (*usb_m->cancel_queued_transfers)(usd->pipe_read);
+ (*usb_m->cancel_queued_transfers)(usd->pipe_write);
+ (*usb_m->cancel_queued_transfers)(usd->pipe_control);
+}
+
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/acm.h b/src/add-ons/kernel/drivers/ports/usb_serial/acm.h
new file mode 100644
index 0000000000..e1043cdd6c
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/acm.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USB_ACM_H_
+ #define _USB_ACM_H_
+
+status_t add_acm_device(usb_serial_device *usd,
+ const usb_configuration_info *uci);
+status_t reset_acm_device(usb_serial_device *usd);
+status_t set_line_coding_acm(usb_serial_device *usd,
+ usb_serial_line_coding *line_coding);
+status_t set_control_line_state_acm(usb_serial_device *usd, uint16 state);
+void on_read_acm(usb_serial_device *usd, char **buf, size_t *num_bytes);
+void on_write_acm(usb_serial_device *usd, const char *buf, size_t *num_bytes);
+void on_close_acm(usb_serial_device *usd);
+
+#endif //_USB_ACM_H_
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.c b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c
new file mode 100644
index 0000000000..80ae4698c1
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.c
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include /* strerror */
+#include /* strtol */
+#include /* sprintf */
+
+#include "driver.h"
+#include "acm.h"
+#include "prolific.h"
+#include "ftdi.h"
+
+/* driver callbacks forward declarations */
+static status_t usb_serial_open (const char *name, uint32 flags, void** cookie);
+static status_t usb_serial_read (void* cookie,
+ off_t position, void *buf, size_t* num_bytes);
+static status_t usb_serial_write (void* cookie, off_t position,
+ const void* buffer, size_t* num_bytes);
+static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len);
+static status_t usb_serial_close (void* cookie);
+static status_t usb_serial_free (void* cookie);
+/* USB notify callbacks forward declarations */
+status_t usb_serial_device_added(const usb_device *dev, void **cookie);
+status_t usb_serial_device_removed(void *cookie);
+
+/* The base name of drivers created in /dev/ports/ directory */
+#define BASENAME_LEN 0x09 /*must be synchronized with below !!!*/
+static const char *basename = "ports/usb%u";
+
+/* function pointers for the device hooks entry points */
+device_hooks usb_serial_hooks = {
+ usb_serial_open, /* -> open entry point */
+ usb_serial_close, /* -> close entry point */
+ usb_serial_free, /* -> free cookie */
+ usb_serial_control, /* -> control entry point */
+ usb_serial_read, /* -> read entry point */
+ usb_serial_write /* -> write entry point */
+};
+/* USB notify hooks */
+static usb_notify_hooks notify_hooks = {
+ &usb_serial_device_added,
+ &usb_serial_device_removed
+};
+/* kernel modules */
+usb_module_info *usb_m; /* usb layer */
+tty_module_info *tty_m; /* tty layer */
+
+struct tty usb_serial_tty[DEVICES_COUNT];
+struct ddomain usb_serial_dd;
+/* hardware devices, supported by this driver.
+ See description field for human readable names */
+usb_serial_hw usb_serial_hw_devices[] = {
+ {0, 0, add_acm_device, reset_acm_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "CDC ACM compatible device"},
+
+ {VND_PROLIFIC, PROD_PROLIFIC_RSAQ2,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "PL2303 Serial adapter (IODATA USB-RSAQ2)"},
+ {VND_IODATA, PROD_IODATA_USBRSAQ,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "I/O Data USB serial adapter USB-RSAQ1"},
+ {VND_ATEN, PROD_ATEN_UC232A,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "Aten Serial adapter"},
+ {VND_TDK, PROD_TDK_UHA6400,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "TDK USB-PHS Adapter UHA6400"},
+ {VND_RATOC, PROD_RATOC_REXUSB60,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "Ratoc USB serial adapter REX-USB60"},
+ {VND_PROLIFIC, PROD_PROLIFIC_PL2303,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "PL2303 Serial adapter (ATEN/IOGEAR UC232A)"},
+ {VND_ELECOM, PROD_ELECOM_UCSGT,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "Elecom UC-SGT"},
+ {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "SOURCENEXT KeikaiDenwa 8"},
+ {VND_SOURCENEXT, PROD_SOURCENEXT_KEIKAI8_CHG,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "SOURCENEXT KeikaiDenwa 8 with charger"},
+ {VND_HAL, PROD_HAL_IMR001,
+ add_prolific_device, reset_prolific_device,
+ set_line_coding_acm, set_control_line_state_acm,
+ on_read_acm, on_write_acm, on_close_acm,
+ "HAL Corporation Crossam2+USB"},
+
+ {VND_FTDI, PROD_8U100AX,
+ add_ftdi_device, reset_ftdi_device,
+ set_line_coding_ftdi, set_control_line_state_ftdi,
+ on_read_ftdi, on_write_ftdi, on_close_ftdi,
+ "FTDI 8U100AX serial converter"},
+ {VND_FTDI, PROD_8U232AM,
+ add_ftdi_device, reset_ftdi_device,
+ set_line_coding_ftdi, set_control_line_state_ftdi,
+ on_read_ftdi, on_write_ftdi, on_close_ftdi,
+ "FTDI 8U232AM serial converter"},
+};
+/* supported devices*/
+usb_support_descriptor supported_devices[] = {
+ {USB_DEV_CLASS_COMM, 0, 0, 0, 0},
+ {0, 0, 0, VND_PROLIFIC, PROD_PROLIFIC_RSAQ2 },
+ {0, 0, 0, VND_IODATA, PROD_IODATA_USBRSAQ },
+ {0, 0, 0, VND_ATEN, PROD_ATEN_UC232A },
+ {0, 0, 0, VND_TDK, PROD_TDK_UHA6400 },
+ {0, 0, 0, VND_RATOC, PROD_RATOC_REXUSB60 },
+ {0, 0, 0, VND_PROLIFIC, PROD_PROLIFIC_PL2303 },
+ {0, 0, 0, VND_ELECOM, PROD_ELECOM_UCSGT },
+
+ {0, 0, 0, VND_FTDI, PROD_8U100AX },
+ {0, 0, 0, VND_FTDI, PROD_8U232AM },
+};
+/* main devices table locking semaphore */
+sem_id usb_serial_lock = -1;
+/* array of pointers to device objects */
+usb_serial_device *usb_serial_devices[DEVICES_COUNT];
+/* the names of "ports" */
+char * usb_serial_names[DEVICES_COUNT + 1];
+/* speed constants, supported by this driver. */
+const uint32 serial_tty_speed[] = {
+ 0x00000000, //B0
+ 0x00000032, //B50
+ 0x0000004B, //B75
+ 0x0000006E, //B110
+ 0x00000086, //B134
+ 0x00000096, //B150
+ 0x000000C8, //B200
+ 0x0000012C, //B300
+ 0x00000258, //B600
+ 0x000004B0, //B1200
+ 0x00000708, //B1800
+ 0x00000960, //B2400
+ 0x000012C0, //B4800
+ 0x00002580, //B9600
+ 0x00004B00, //B19200
+ 0x00009600, //B38400
+ 0x0000E100, //B57600
+ 0x0001C200, //B115200
+ 0x00038400, //B230400
+ 0x00070800, //460800
+ 0x000E1000, //921600
+};
+
+/* init_hardware - called once the first time the driver is loaded */
+status_t init_hardware (void){
+ TRACE("init_hardware\n"); /*special case - no file-logging activated now*/
+ return B_OK;
+}
+
+/* init_driver - optional function - called every time the driver
+ is loaded. */
+status_t init_driver (void){
+ int i;
+ status_t status = B_OK;
+ load_setting();
+ create_log();
+
+ TRACE_FUNCALLS("init_driver\n");
+
+ if((status = get_module(B_TTY_MODULE_NAME, (module_info **)&tty_m)) == B_OK){
+ if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb_m)) == B_OK){
+ if(tty_m && usb_m){
+ for(i = 0; i < DEVICES_COUNT; i++)
+ usb_serial_devices[i] = 0;
+
+ usb_serial_names[0] = NULL;
+ load_driver_symbols(DRIVER_NAME);
+
+ (*usb_m->register_driver)(DRIVER_NAME, supported_devices,
+ SIZEOF(supported_devices), DRIVER_NAME);
+ (*usb_m->install_notify)(DRIVER_NAME, ¬ify_hooks);
+
+ usb_serial_lock = create_sem(1, DRIVER_NAME"_devices_table_lock");
+ }else{
+ status = B_ERROR;
+ TRACE_ALWAYS("init_driver failed: tty_m:%08x usb_m:%08x", tty_m, usb_m);
+ }
+ }else
+ TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status,
+ B_USB_MODULE_NAME);
+ }else
+ TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status,
+ B_TTY_MODULE_NAME);
+
+ TRACE_FUNCRET("init_driver returns:%08x\n", status);
+ return status;
+}
+
+/* uninit_driver - optional function - called every time the driver
+ is unloaded */
+void uninit_driver (void){
+ int i;
+ TRACE_FUNCALLS("uninit_driver\n");
+
+ (*usb_m->uninstall_notify)(DRIVER_NAME);
+ acquire_sem(usb_serial_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++)
+ if(usb_serial_devices[i]){
+ delete_area(usb_serial_devices[i]->buffers_area);
+ delete_sem(usb_serial_devices[i]->done_read);
+ delete_sem(usb_serial_devices[i]->done_write);
+ free(usb_serial_devices[i]);
+ usb_serial_devices[i] = 0;
+ }
+
+ release_sem_etc(usb_serial_lock, 1, B_DO_NOT_RESCHEDULE);
+ delete_sem(usb_serial_lock);
+
+ for(i = 0; usb_serial_names[i]; i++)
+ free(usb_serial_names[i]);
+
+ put_module(B_USB_MODULE_NAME);
+ put_module(B_TTY_MODULE_NAME);
+}
+
+void usb_serial_device_notify_in(void *cookie,
+ uint32 status, void *data, uint32 actual_len){
+ TRACE_FUNCALLS("usb_serial_device_notify_in:cookie:%08x status:%08x data:%08x len:%d\n", cookie, status, data, actual_len);
+ if(cookie){
+ usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device;
+ usd->actual_len_read = actual_len;
+ usd->dev_status_read = status;
+ release_sem(usd->done_read);
+ }
+}
+
+void usb_serial_device_notify_out(void *cookie, uint32 status,
+ void *data, uint32 actual_len){
+ TRACE_FUNCALLS("usb_serial_device_notify_out:cookie:%08x status:%08x "
+ "data:%08x len:%d\n", cookie, status, data, actual_len);
+ if(cookie){
+ usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device;
+ usd->actual_len_write = actual_len;
+ usd->dev_status_write = status;
+ release_sem(usd->done_write);
+ }
+}
+
+status_t usb_serial_device_thread(void *param){
+ status_t status = B_ERROR;
+ usb_serial_device_info *usdi = (usb_serial_device_info *)param;
+ usb_serial_device *usd = usdi->device;
+ TRACE_FUNCALLS("usb_serial_device_thread:%08x\n", param);
+
+ while(true){
+ size_t i, to_read;
+ char *buf;
+ struct ddrover *ddr;
+ usd->actual_len_read = 0;
+ usd->dev_status_read = 0;
+ status = (*usb_m->queue_bulk)(usd->pipe_read, usd->read_buffer,
+ usd->read_buffer_size, usb_serial_device_notify_in, usdi);
+ if(status != B_OK){
+ TRACE_ALWAYS("usb_serial_device_thread : queue_bulk error : %lx\n", status);
+ break;
+ }
+
+ status = acquire_sem_etc(usd->done_read, 1, B_CAN_INTERRUPT, 0);
+ if(status != B_OK){
+ TRACE_ALWAYS("usb_serial_device_thread : acquire_sem_etc : "
+ "error %08lx (%s)\n", status, strerror(status));
+ break;
+ }
+
+ if(usd->dev_status_read){
+ TRACE_ALWAYS("usb_serial_device_thread : dev_status error !!!\n");
+ break;
+ }
+
+ buf = usd->read_buffer;
+ to_read = usd->actual_len_read;
+ (*usd->hw->on_read)(usd, &buf, &to_read);
+
+ if(!to_read)
+ continue;
+
+ ddr = (*tty_m->ddrstart)(NULL);
+ if(!ddr){
+ TRACE_ALWAYS("usb_serial_device_thread : ddrstart problem !!!\n");
+ status = B_NO_MEMORY;
+ break;
+ }
+
+ (*tty_m->ttyilock)(usd->tty, ddr, true);
+ for(i = 0; i < to_read; i++){
+ (*tty_m->ttyin)(usd->tty, ddr, buf[i]);
+ }
+ (*tty_m->ttyilock)(usd->tty, ddr, false);
+ (*tty_m->ddrdone)(ddr);
+ }
+
+ TRACE_FUNCRET("usb_serial_device_thread returns %08x\n", status);
+ return status;
+}
+
+void usb_serial_setmodes(usb_serial_device *usd){
+ usb_serial_line_coding line_coding;
+ struct termios tios;
+
+ int newctrl, baud_index;
+ TRACE_FUNCALLS("usb_serial_setmodes:%08x\n", usd);
+
+ memcpy(&tios, &usd->tty->t, sizeof(struct termios));
+ newctrl = usd->ctrlout;
+
+ TRACE_FUNCRES(trace_termios, &tios);
+ TRACE("newctrl:%08x\n", newctrl);
+
+ baud_index = tios.c_cflag & CBAUD;
+ if(baud_index > SIZEOF(serial_tty_speed))
+ baud_index = SIZEOF(serial_tty_speed) - 1;
+
+ line_coding.speed = serial_tty_speed[baud_index];
+ line_coding.stopbits = ( tios.c_cflag & CSTOPB ) ? LC_STOP_BIT_2 : LC_STOP_BIT_1;
+
+ if(PARENB & tios.c_cflag){
+ line_coding.parity = LC_PARITY_EVEN;
+
+ if(PARODD & tios.c_cflag){
+ line_coding.parity = LC_PARITY_ODD;
+ }
+ }else
+ line_coding.parity = LC_PARITY_NONE;
+
+ line_coding.databits = (tios.c_cflag & CS8) ? 8 : 7;
+
+ if(line_coding.speed == 0){
+ newctrl &= 0xfffffffe;
+ line_coding.speed = usd->line_coding.speed;
+ }else
+ newctrl = CLS_LINE_DTR;
+
+ if(usd->ctrlout != newctrl ){
+ usd->ctrlout = newctrl;
+ TRACE("newctrl send to modem:%08x\n", newctrl);
+ (*usd->hw->set_control_line_state)(usd, newctrl);
+ }
+
+ if(memcmp (&line_coding, &usd->line_coding, sizeof(usb_serial_line_coding))){
+ usd->line_coding.speed = line_coding.speed;
+ usd->line_coding.stopbits = line_coding.stopbits;
+ usd->line_coding.databits = line_coding.databits;
+ usd->line_coding.parity = line_coding.parity;
+ TRACE("send to modem:speed %d sb:%08x db:%08x parity:%08x\n",
+ usd->line_coding.speed, usd->line_coding.stopbits,
+ usd->line_coding.databits, usd->line_coding.parity);
+ (*usd->hw->set_line_coding)(usd, &usd->line_coding);
+ }
+}
+
+bool usb_serial_service(struct tty *ptty, struct ddrover *ddr, uint flags){
+ int i;
+ bool bret = false;
+ usb_serial_device *usd;
+ TRACE_FUNCALLS("usb_serial_service:%08x ddr:%08x flags:%08x\n", ptty, ddr, flags);
+
+ for(i = 0; i < DEVICES_COUNT; i++){
+ if(usb_serial_devices[i]){
+ if(ptty == usb_serial_devices[i]->tty){
+ usd = usb_serial_devices[i];
+ break;
+ }
+ }
+ }
+
+ if(usd){
+ if(flags <= TTYGETSIGNALS){
+ switch(flags){
+ case TTYENABLE:
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false);
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true);
+
+ usd->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS;
+ (*usd->hw->set_control_line_state)(usd, usd->ctrlout);
+ break;
+
+ case TTYDISABLE:
+
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, false);
+
+ usd->ctrlout = 0x0;
+ (*usd->hw->set_control_line_state)(usd, usd->ctrlout);
+ break;
+
+ case TTYISTOP:
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, false);
+ break;
+
+ case TTYIRESUME:
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true);
+ break;
+
+ case TTYGETSIGNALS:
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDCD, true);
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWCTS, true);
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWDSR, false);
+ (*tty_m->ttyhwsignal)(ptty, ddr, TTYHWRI, false);
+ break;
+
+ case TTYSETMODES:
+ usb_serial_setmodes(usd);
+ break;
+
+ case TTYOSTART:
+ case TTYOSYNC:
+ case TTYSETBREAK:
+ case TTYCLRBREAK:
+ case TTYSETDTR:
+ case TTYCLRDTR:
+ break;
+ }
+ }
+ bret = true;
+ }
+
+ TRACE_FUNCRET("usb_serial_service returns %d\n", bret);
+ return bret;
+}
+
+void usb_serial_notify_interrupt(void *cookie, uint32 status,
+ void *data, uint32 actual_len){
+ TRACE_FUNCALLS("usb_serial_notify_interrupt : %p %lx %p %ld\n",
+ cookie, status, data, actual_len);
+ if(cookie){
+ usb_serial_device *usd = ((usb_serial_device_info *)cookie)->device;
+ usd->actual_len_interrupt = actual_len;
+ usd->dev_status_interrupt = status;
+ }
+}
+
+/* usb_serial_open - handle open() calls */
+static status_t usb_serial_open (const char *name, uint32 flags, void** cookie){
+ int i;
+ status_t status = ENODEV;
+ TRACE_FUNCALLS("usb_serial_open:%s flags:%d cookie:%08x\n",
+ name, flags, cookie);
+
+ for(i=0;i= 0 && i < DEVICES_COUNT){
+ acquire_sem(usb_serial_lock);
+ if(usb_serial_devices[i]){
+ usb_serial_device_info *usdi = malloc(sizeof(usb_serial_device_info));
+ if(usdi){
+ struct ddrover *ddr;
+ memset(usdi, 0, sizeof(usb_serial_device_info));
+ *cookie = usdi;
+
+ TRACE("cookie in open:%08x\n", *cookie);
+
+ usdi->device = usb_serial_devices[i];
+
+ (*tty_m->ttyinit)(&usb_serial_tty[i], true);
+
+ usdi->ttyfile.tty = &usb_serial_tty[i];
+ usdi->ttyfile.flags = flags;
+ usb_serial_devices[i]->tty = &usb_serial_tty[i];
+
+ (*usdi->device->hw->reset_device)(usdi->device);
+
+ TRACE("Opened:%s %08x\n", usdi->device->hw->descr, usdi->device->dev);
+
+ ddr = (*tty_m->ddrstart)(NULL);
+ if(ddr){
+ (*tty_m->ddacquire)(ddr, &usb_serial_dd);
+ status = (*tty_m->ttyopen)(&usdi->ttyfile, ddr, usb_serial_service);
+ (*tty_m->ddrdone)(ddr);
+
+ if(status == B_OK){
+ sem_id sem = spawn_kernel_thread(usb_serial_device_thread,
+ "usb_serial_device_thread", 0xa, usdi);
+ if(sem != -1)
+ resume_thread(sem);
+ else
+ TRACE_ALWAYS("usb_serial_open: cannot spawn kernel thread!!!\n");
+
+ usdi->device->ctrlout = CLS_LINE_DTR | CLS_LINE_RTS;
+ (*usdi->device->hw->set_control_line_state)(usdi->device,
+ usdi->device->ctrlout);
+
+ status = (*usb_m->queue_interrupt)(usdi->device->pipe_control,
+ usdi->device->interrupt_buffer,
+ usdi->device->interrupt_buffer_size,
+ usb_serial_notify_interrupt, usdi);
+ }
+ }else
+ status = B_NO_MEMORY;
+
+ if(status != B_OK)
+ free(usdi);
+ }else
+ status = B_NO_MEMORY;
+ }
+ release_sem(usb_serial_lock);
+ }
+
+ TRACE_FUNCRET("usb_serial_open returns:%08x\n", status);
+ return status;
+}
+
+/* usb_serial_read - handle read() calls */
+static status_t usb_serial_read (void* cookie, off_t position,
+ void *buf, size_t* num_bytes){
+ status_t status = B_OK;
+ struct ddrover *ddr;
+ TRACE_FUNCALLS("usb_serial_read:%08x position:%Ld buf:%08x len:%d\n",
+ cookie, position, buf, *num_bytes);
+
+ ddr = (*tty_m->ddrstart)(NULL);
+ if(ddr){
+ if(cookie)
+ status = (*tty_m->ttyread)(cookie, ddr, buf, num_bytes);
+ else
+ (*tty_m->ddacquire)(ddr, &usb_serial_dd);
+ (*tty_m->ddrdone)(ddr);
+ }else{
+ TRACE_ALWAYS("usb_serial_read : ddrstart problem !!!\n");
+ status = B_NO_MEMORY;
+ }
+
+ TRACE_FUNCRET("usb_serial_read returns:%08x readed:%d\n", status, *num_bytes);
+ return status;
+}
+
+/* usb_serial_write - handle write() calls */
+
+static status_t usb_serial_write (void* cookie, off_t position,
+ const void* buffer, size_t* num_bytes){
+ status_t status = B_OK;
+ usb_serial_device_info *usdi = (usb_serial_device_info *)cookie;
+ usb_serial_device *usd = usdi->device;
+ size_t to_write = *num_bytes;
+ TRACE_FUNCALLS("usb_serial_write:%08x position:%Ld buf:%08x len:%d\n",
+ cookie, position, buffer, *num_bytes);
+ *num_bytes = 0; /* tell caller nothing was written */
+
+ while(to_write > 0){
+ size_t len = to_write;
+
+ (*usd->hw->on_write)(usd, buffer, &len);
+
+ usd->actual_len_write = 0;
+ usd->dev_status_write = 0;
+
+ status = (*usb_m->queue_bulk)(usd->pipe_write, usd->write_buffer,
+ len, usb_serial_device_notify_out, cookie);
+ if(status != B_OK){
+ TRACE_ALWAYS("usb_serial_write : dev %p status %lx", cookie, status);
+ break;
+ }
+
+ status = acquire_sem_etc(usd->done_write, 1, B_CAN_INTERRUPT, 0);
+ if(status != B_OK){
+ TRACE_ALWAYS("usb_serial_write : acquire_sem_etc() %lx (%s)",
+ status, strerror(status));
+ break;
+ }
+
+ ((const char*)buffer) += usd->actual_len_write;
+ *num_bytes += usd->actual_len_write;
+ to_write -= usd->actual_len_write;
+ }
+
+ TRACE_FUNCRET("usb_serial_write returns:%08x written:%d\n", status, *num_bytes);
+ return status;
+}
+
+/* usb_serial_control - handle ioctl calls */
+static status_t usb_serial_control (void* cookie, uint32 op, void* arg, size_t len){
+ status_t status = B_BAD_VALUE;
+ TRACE_FUNCALLS("usb_serial_control cookie:%08x op:%08x arg:%08x len:%d\n",
+ cookie, op, arg, len);
+
+ if(cookie){
+ struct ddrover *ddr = (*tty_m->ddrstart)(NULL);
+ if(ddr){
+ status = (*tty_m->ttycontrol)(cookie, ddr, op, arg, len);
+ (*tty_m->ddrdone)(ddr);
+ }else
+ status = B_NO_MEMORY;
+ }else
+ status = ENODEV;
+
+ TRACE_FUNCRET("usb_serial_control returns:%08x\n", status);
+ return status;
+}
+
+/* usb_serial_close - handle close() calls */
+static status_t usb_serial_close (void* cookie){
+ status_t status = ENODEV;
+ TRACE_FUNCALLS("usb_serial_close:%08x\n", cookie);
+
+ if(cookie){
+ usb_serial_device_info *usdi = (usb_serial_device_info *)cookie;
+ usb_serial_device *usd = usdi->device;
+ struct ddrover *ddr;
+
+ (*usd->hw->on_close)(usd);
+
+ ddr = (*tty_m->ddrstart)(NULL);
+ if(ddr){
+ status = (*tty_m->ttyclose)(cookie, ddr);
+ (*tty_m->ddrdone)(ddr);
+ }else
+ status = B_NO_MEMORY;
+ }
+
+ TRACE_FUNCRET("usb_serial_close returns:%08x\n", status);
+ return status;
+}
+
+/* usb_serial_free - called after the last device is closed, and after
+ all i/o is complete.*/
+static status_t usb_serial_free (void* cookie){
+ status_t status = B_OK;
+ TRACE_FUNCALLS("usb_serial_free:%08x\n", cookie);
+
+ if(cookie){
+ struct ddrover *ddr = (*tty_m->ddrstart)(NULL);
+ if(ddr){
+ status = (*tty_m->ttyfree)(cookie, ddr);
+ (*tty_m->ddrdone)(ddr);
+ }else
+ status = B_NO_MEMORY;
+ free(cookie);
+ }
+
+ TRACE_FUNCRET("usb_serial_free returns:%08x\n", status);
+ return status;
+}
+
+/* publish_devices - return a null-terminated array of devices
+ supported by this driver. */
+const char** publish_devices(){
+ int i, j;
+ TRACE_FUNCALLS("publish_devices\n");
+
+ for(i=0; usb_serial_names[i]; i++)
+ free(usb_serial_names[i]);
+
+ acquire_sem(usb_serial_lock);
+ for(i=0, j=0; i < DEVICES_COUNT; i++){
+ if(usb_serial_devices[i]){
+ usb_serial_names[j] = malloc(strlen(basename + 2));
+ if(usb_serial_names[j]){
+ sprintf(usb_serial_names[j], basename, i);
+ j++;
+ }
+ else
+ TRACE_ALWAYS("publish_devices - NO MEMORY\n");
+ }
+ }
+ usb_serial_names[j] = NULL;
+ release_sem(usb_serial_lock);
+
+ return (const char **)&usb_serial_names[0];
+}
+
+/* find_device - return ptr to device hooks structure for a
+ given device name */
+device_hooks* find_device(const char* name){
+ TRACE_FUNCALLS("find_device(%s)\n", name);
+ return &usb_serial_hooks;
+}
+
+status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci,
+ usb_endpoint_info *comm_epi,
+ usb_endpoint_info *data_out_epi,
+ usb_endpoint_info *data_in_epi){
+ char name[32];
+ status_t status = ENODEV;
+ size_t buf_len;
+ int i = 0;
+
+ TRACE_FUNCALLS("add_device(%08x, %08x, %08x, %08x, %08x)\n",
+ usd, uci, comm_epi, data_in_epi, data_out_epi);
+
+ acquire_sem(usb_serial_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++){
+ if(usb_serial_devices[i] != NULL)
+ continue;
+
+ usb_serial_devices[i] = usd;
+
+ usd->active = 1;
+ usd->open = 0;
+
+ sprintf(name, "usb_serial:%d:done_read", i );
+ usd->done_read = create_sem(0, name);
+
+ sprintf(name, "usb_serial:%d:done_write", i);
+ usd->done_write = create_sem(0, name);
+
+ usd->tty = NULL;
+
+ buf_len = usd->read_buffer_size + usd->write_buffer_size +
+ usd->interrupt_buffer_size;
+
+ usd->buffers_area = create_area("usb_serial:buffers_area",
+ (void *)&usd->read_buffer,
+ B_ANY_KERNEL_ADDRESS,
+ ROUNDUP(buf_len, B_PAGE_SIZE),
+ B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA);
+
+ usd->write_buffer = usd->read_buffer + usd->read_buffer_size;
+ usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size;
+
+ (*usb_m->set_configuration)(usd->dev, uci);
+
+ usd->pipe_control = (comm_epi) ? comm_epi->handle : 0;
+ usd->pipe_write = data_out_epi->handle;
+ usd->pipe_read = data_in_epi->handle;
+
+ status = B_OK;
+ break;
+ }
+
+ release_sem(usb_serial_lock);
+
+ TRACE_FUNCRET("add_device returns:%08x\n", status);
+ return status;
+}
+
+
+status_t usb_serial_device_added(const usb_device *dev, void **cookie){
+ int i;
+ status_t status = B_OK;
+ const usb_device_descriptor *udd;
+ usb_serial_device *usd = 0;
+ TRACE_FUNCALLS("usb_serial_device_added:%08x cookie:%08x\n", dev, cookie);
+
+ udd = (*usb_m->get_device_descriptor)(dev);
+
+ TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id);
+
+ *cookie = 0;
+ for(i=1; i < sizeof(usb_serial_hw_devices)/sizeof(usb_serial_hw_devices[0]); i++)
+ if(usb_serial_hw_devices[i].vendor_id == udd->vendor_id
+ && usb_serial_hw_devices[i].product_id == udd->product_id){
+ const usb_configuration_info *uci;
+ uci = (*usb_m->get_nth_configuration)(dev, 0);
+ if(uci){
+ usd = malloc(sizeof(usb_serial_device));
+ if(usd){
+ usd->dev = dev;
+ usd->hw = &usb_serial_hw_devices[i];
+ usd->read_buffer_size =
+ usd->write_buffer_size =
+ usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16);
+ if((status = (*usb_serial_hw_devices[i].add_device)(usd, uci)) == B_OK){
+ *cookie = dev;
+ TRACE_ALWAYS("%s (%04x/%04x) added \n",
+ usb_serial_hw_devices[i].descr,
+ usb_serial_hw_devices[i].vendor_id,
+ usb_serial_hw_devices[i].product_id);
+ }else
+ free(usd);
+ }else
+ status = B_NO_MEMORY;
+ }
+ break;
+ }
+
+ if(!*cookie){
+ if(b_acm_support &&
+ udd->device_class == USB_DEV_CLASS_COMM &&
+ udd->device_subclass == 0 &&
+ udd->device_protocol == 0 ){
+ const usb_configuration_info *uci;
+ uint16 idx = 0;
+ do{
+ uci = (*usb_m->get_nth_configuration)(dev, idx++);
+ if(uci){
+ if(uci->interface_count != 2)
+ continue;
+ usd = malloc(sizeof(usb_serial_device));
+ if(usd){
+ usd->dev = dev;
+ usd->hw = &usb_serial_hw_devices[0];
+ usd->read_buffer_size =
+ usd->write_buffer_size =
+ usd->interrupt_buffer_size = ROUNDUP(DEF_BUFFER_SIZE, 16);
+ if((status = (*usb_serial_hw_devices[0].add_device)(usd, uci)) == B_OK){
+ *cookie = dev;
+ TRACE_ALWAYS("%s (%04x/%04x) added \n",
+ usb_serial_hw_devices[0].descr,
+ udd->vendor_id, udd->product_id);
+ }else
+ free(usd);
+ }else
+ status = B_NO_MEMORY;
+ }
+ }while(uci);
+ }else{
+ TRACE_ALWAYS("device has wrong class, subclass and protocol\n");
+ status = B_ERROR;
+ }
+ }
+ TRACE_FUNCRET("usb_serial_device_added returns:%08x\n", status);
+ return status;
+}
+
+status_t usb_serial_device_removed(void *cookie){
+ int i;
+ status_t status = B_OK;
+ usb_device *ud = (usb_device *) cookie;
+ TRACE_FUNCALLS("usb_serial_device_removed:%08x\n", cookie);
+
+ acquire_sem(usb_serial_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++ ){
+ usb_serial_device *usd = usb_serial_devices[i];
+ if(usd){
+ if(ud == usd->dev){
+ usd->active = 0;
+ if(!usd->open)
+ break;
+
+ delete_area(usd->buffers_area);
+ delete_sem(usd->done_read);
+ delete_sem(usd->done_write);
+ free(usd);
+ usb_serial_devices[i] = 0;
+ }
+ }
+ }
+
+ release_sem(usb_serial_lock);
+
+ TRACE_FUNCRET("usb_serial_device_removed returns:%08x\n", status);
+ return status;
+}
+
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/driver.h b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h
new file mode 100644
index 0000000000..885fd642cf
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/driver.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USB_SERIAL_DRIVER_H_
+ #define _USB_SERIAL_DRIVER_H_
+
+/* The name of this driver ... */
+#define DRIVER_NAME "usb_serial"
+/* Maximal count of devices supported by this driver at the same time. */
+#define DEVICES_COUNT 20
+
+#include "tracing.h"
+
+/* Some usefull helper defines ... */
+#define SIZEOF(array) (sizeof(array)/sizeof(array[0])) /* size of array */
+/* This one rounds the size to integral count of segs (segments) */
+#define ROUNDUP(size, seg) (((size) + (seg) - 1) & ~((seg) - 1))
+/* buffer size */
+#define DEF_BUFFER_SIZE 0x100
+
+/* line coding defines ... Come from CDC USB specs? */
+#define LC_STOP_BIT_1 0
+#define LC_STOP_BIT_2 2
+
+#define LC_PARITY_NONE 0
+#define LC_PARITY_ODD 1
+#define LC_PARITY_EVEN 2
+/* struct that represents line coding */
+typedef struct _s_usb_serial_line_coding{
+ uint32 speed;
+ uint8 stopbits;
+ uint8 parity;
+ uint8 databits;
+} usb_serial_line_coding;
+
+/* "forgotten" requests for CDC ACM devices */
+#define SET_LINE_CODING 0x20
+#define SET_CONTROL_LINE_STATE 0x22
+
+/* control line states */
+#define CLS_LINE_DTR 0x0001
+#define CLS_LINE_RTS 0x0002
+
+/* "forgotten" attributes etc ...*/
+#define USB_EP_ADDR_DIR_IN 0x80
+#define USB_EP_ADDR_DIR_OUT 0x00
+
+#define USB_EP_ATTR_CONTROL 0x00
+#define USB_EP_ATTR_ISOCHRONOUS 0x01
+#define USB_EP_ATTR_BULK 0x02
+#define USB_EP_ATTR_INTERRUPT 0x03
+/* USB class - communication devices */
+#define USB_DEV_CLASS_COMM 0x02
+
+#define USB_INT_CLASS_CDC 0x02
+#define USB_INT_SUBCLASS_ABSTRACT_CONTROL_MODEL 0x02
+
+#define USB_INT_CLASS_CDC_DATA 0x0a
+#define USB_INT_SUBCLASS_DATA 0x00
+
+/* a kind of forward declaration */
+typedef struct _s_usb_serial_device usb_serial_device;
+
+/* usb_serial_hw - represents the different hardware devices */
+typedef struct _s_usb_serial_hw{
+ uint16 vendor_id; /* vendor id and card id of device */
+ uint16 product_id;
+ /* callbacks used in "customization" of the driver behaviour */
+ status_t (*add_device)(usb_serial_device *usd,
+ const usb_configuration_info *uci);
+ status_t (*reset_device)(usb_serial_device *usd);
+ status_t (*set_line_coding)(usb_serial_device *usd,
+ usb_serial_line_coding *line_coding);
+ status_t (*set_control_line_state)(usb_serial_device *usd, uint16 state);
+ void (*on_read)(usb_serial_device *usd, char **buf, size_t *num_bytes);
+ void (*on_write)(usb_serial_device *usd, const char *buf,
+ size_t *num_bytes);
+ void (*on_close)(usb_serial_device *usd);
+ const char *descr; /* informational description */
+}usb_serial_hw;
+
+status_t add_device(usb_serial_device *usd, const usb_configuration_info *uci,
+ usb_endpoint_info *comm_epi,
+ usb_endpoint_info *data_out_epi,
+ usb_endpoint_info *data_in_epi);
+
+/* this one was typedefed into usb_serial_device - see above for details
+ this struct represents the main device object */
+struct _s_usb_serial_device{
+ int active; /* is device active - performing some tasks */
+ int32 open; /* is device opened */
+ const usb_device *dev; /* points to usb device handle */
+ /* communication pipes */
+ usb_pipe *pipe_control;
+ usb_pipe *pipe_read;
+ usb_pipe *pipe_write;
+ /* line coding */
+ usb_serial_line_coding line_coding;
+
+ /* data buffers */
+ area_id buffers_area;
+ /* read buffer */
+ char *read_buffer;
+ size_t read_buffer_size;
+ /* write buffer */
+ char *write_buffer;
+ size_t write_buffer_size;
+ /* interrupt buffer */
+ char *interrupt_buffer;
+ size_t interrupt_buffer_size;
+
+ /* variables used in callback functionality */
+ size_t actual_len_read;
+ uint32 dev_status_read;
+ size_t actual_len_write;
+ uint32 dev_status_write;
+ size_t actual_len_interrupt;
+ uint32 dev_status_interrupt;
+ /* semaphores used in callbacks */
+ sem_id done_read;
+ sem_id done_write;
+
+ uint16 ctrlout;
+
+ struct tty *tty;
+
+ usb_serial_hw *hw; /* points to corresponding hardware description */
+ /* place for device specific data */
+ union{
+ struct _spec_acm{ /* ACM-compatible devices */
+ }acm;
+ struct _spec_prolific{ /* Prolific devices*/
+ }prolific;
+ struct _spec_ftdi{ /* FTDI devices*/
+ uint8 hdrlen;
+ uint8 status_msr;
+ uint8 status_lsr;
+ }ftdi;
+ }spec;
+}; /*already typedef-ed - see comment above! */
+/* high-level of abstraction of the device*/
+typedef struct _s_usb_serial_device_info{
+ struct ttyfile ttyfile; /* */
+ usb_serial_device *device; /* */
+}usb_serial_device_info;
+
+extern usb_serial_device *usb_serial_devices[];
+extern char * usb_serial_names[];
+extern usb_module_info *usb_m;
+
+#endif//_USB_SERIAL_DRIVER_H_
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c
new file mode 100644
index 0000000000..7bcfc3deee
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "driver.h"
+#include "ftdi.h"
+#include "uftdireg.h"
+
+
+status_t add_ftdi_device(usb_serial_device *usd,
+ const usb_configuration_info *uci)
+{
+ struct usb_endpoint_info *comm_epi = NULL;
+ struct usb_endpoint_info *data_out_epi = NULL;
+ struct usb_endpoint_info *data_in_epi = NULL;
+ status_t status = ENODEV;
+ int i = 0;
+
+ TRACE_FUNCALLS("> add_ftdi_device(%08x, %08x)\n", usd, uci);
+
+ if(uci->interface_count){
+ struct usb_interface_info *uii = uci->interface[0].active;
+ for(i = 0; i < uii->endpoint_count; i++){
+ if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){
+ if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
+ == USB_EP_ADDR_DIR_IN){
+ data_in_epi = &uii->endpoint[i];
+ }else{
+ if(uii->endpoint[i].descr->endpoint_address
+ /*USB_EP_ADDR_DIR_OUT = 0x0*/){
+ comm_epi = data_out_epi = &uii->endpoint[i];
+ }
+ }
+ }
+ }
+
+ if(comm_epi && data_in_epi && data_out_epi){
+ if(usd->hw->product_id == PROD_8U100AX)
+ usd->spec.ftdi.hdrlen = 1;
+ else
+ usd->spec.ftdi.hdrlen = 0;
+
+ usd->read_buffer_size =
+ usd->write_buffer_size =
+ usd->interrupt_buffer_size = ROUNDUP(FTDI_BUF_SIZE, 16);
+ status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi);
+ }
+ }
+
+ TRACE_FUNCRET("< add_ftdi_device returns:%08x\n", status);
+ return status;
+}
+
+status_t reset_ftdi_device(usb_serial_device *usd){
+ status_t status = B_OK;
+ size_t len = 0;
+ TRACE_FUNCALLS("> reset_ftdi_device(%08x)\n", usd);
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
+ FTDI_SIO_RESET, FTDI_SIO_RESET_SIO,
+ FTDI_PIT_DEFAULT, 0, 0, 0, &len);
+ TRACE_FUNCRET("< reset_ftdi_device returns:%08x\n", status);
+ return status;
+}
+
+status_t set_line_coding_ftdi(usb_serial_device *usd,
+ usb_serial_line_coding *line_coding){
+ status_t status = B_OK;
+ int32 rate, data = 0;
+ size_t len1 = 0, len2 = 0;
+ TRACE_FUNCALLS("> set_line_coding_ftdi(%08x, {%d, %02x, %02x, %02x})\n",
+ usd, line_coding->speed,
+ line_coding->stopbits,
+ line_coding->parity,
+ line_coding->databits);
+
+ if(usd->hw->product_id == PROD_8U100AX){
+ switch (line_coding->speed){
+ case 300: rate = ftdi_sio_b300; break;
+ case 600: rate = ftdi_sio_b600; break;
+ case 1200: rate = ftdi_sio_b1200; break;
+ case 2400: rate = ftdi_sio_b2400; break;
+ case 4800: rate = ftdi_sio_b4800; break;
+ case 9600: rate = ftdi_sio_b9600; break;
+ case 19200: rate = ftdi_sio_b19200; break;
+ case 38400: rate = ftdi_sio_b38400; break;
+ case 57600: rate = ftdi_sio_b57600; break;
+ case 115200: rate = ftdi_sio_b115200; break;
+ default:
+ rate = ftdi_sio_b19200;
+ TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported "
+ "by this hardware. Defaulted to %d\n",
+ line_coding->speed, rate);
+ break;
+ }
+ }else{
+ switch(line_coding->speed){
+ case 300: rate = ftdi_8u232am_b300; break;
+ case 600: rate = ftdi_8u232am_b600; break;
+ case 1200: rate = ftdi_8u232am_b1200; break;
+ case 2400: rate = ftdi_8u232am_b2400; break;
+ case 4800: rate = ftdi_8u232am_b4800; break;
+ case 9600: rate = ftdi_8u232am_b9600; break;
+ case 19200: rate = ftdi_8u232am_b19200; break;
+ case 38400: rate = ftdi_8u232am_b38400; break;
+ case 57600: rate = ftdi_8u232am_b57600; break;
+ case 115200: rate = ftdi_8u232am_b115200; break;
+ case 230400: rate = ftdi_8u232am_b230400; break;
+ case 460800: rate = ftdi_8u232am_b460800; break;
+ case 921600: rate = ftdi_8u232am_b921600; break;
+ default:
+ rate = ftdi_sio_b19200;
+ TRACE_ALWAYS("= set_line_coding_ftdi: Datarate:%d is not supported "
+ "by this hardware. Defaulted to %d\n",
+ line_coding->speed, rate);
+ break;
+ }
+ }
+
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
+ FTDI_SIO_SET_BAUD_RATE, rate,
+ FTDI_PIT_DEFAULT, 0, 0, 0, &len1);
+ if(status != B_OK)
+ TRACE_ALWAYS("= set_line_coding_ftdi: datarate set request failed:%08x",
+ status);
+
+ switch(line_coding->stopbits){
+ case LC_STOP_BIT_2: data = FTDI_SIO_SET_DATA_STOP_BITS_2; break;
+ case LC_STOP_BIT_1: data = FTDI_SIO_SET_DATA_STOP_BITS_1; break;
+ default:
+ TRACE_ALWAYS("= set_line_coding_ftdi: Wrong stopbits param:%d",
+ line_coding->stopbits);
+ break;
+ }
+
+ switch(line_coding->parity){
+ case LC_PARITY_NONE: data |= FTDI_SIO_SET_DATA_PARITY_NONE; break;
+ case LC_PARITY_EVEN: data |= FTDI_SIO_SET_DATA_PARITY_EVEN; break;
+ case LC_PARITY_ODD: data |= FTDI_SIO_SET_DATA_PARITY_ODD; break;
+ default:
+ TRACE_ALWAYS("= set_line_coding_ftdi: Wrong parity param:%d",
+ line_coding->parity);
+ break;
+ }
+
+ switch(line_coding->databits){
+ case 8: data |= FTDI_SIO_SET_DATA_BITS(8); break;
+ case 7: data |= FTDI_SIO_SET_DATA_BITS(7); break;
+ default:
+ TRACE_ALWAYS("= set_line_coding_ftdi: Wrong databits param:%d",
+ line_coding->databits);
+ break;
+ }
+
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
+ FTDI_SIO_SET_DATA, data,
+ FTDI_PIT_DEFAULT, 0, 0, 0, &len2);
+ if(status != B_OK)
+ TRACE_ALWAYS("= set_line_coding_ftdi: data set request failed:%08x",
+ status);
+
+ TRACE_FUNCRET("< set_line_coding_ftdi returns:%08x\n", status);
+ return status;
+}
+
+status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state){
+ status_t status = B_OK;
+ int32 ctrl;
+ size_t len = 0;
+ TRACE_FUNCALLS("> set_control_line_state_ftdi(%08x, %04x)\n", usd, state);
+
+ ctrl = (state & CLS_LINE_RTS) ?
+ FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW;
+ ctrl |= (state & CLS_LINE_DTR) ?
+ FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW;
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
+ FTDI_SIO_MODEM_CTRL, ctrl,
+ FTDI_PIT_DEFAULT, 0, 0, 0, &len);
+ if(status != B_OK)
+ TRACE_ALWAYS("= set_control_line_state_ftdi: control set request "
+ "failed:%08x", status);
+
+ TRACE_FUNCRET("< set_control_line_state_ftdi returns:%08x\n", status);
+ return status;
+}
+
+void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes){
+ usd->spec.ftdi.status_msr = FTDI_GET_MSR(*buf);
+ usd->spec.ftdi.status_lsr = FTDI_GET_LSR(*buf);
+ TRACE("MSR:%02x LSR:%02x\n", usd->spec.ftdi.status_msr,
+ usd->spec.ftdi.status_lsr);
+ *buf += 2;
+ *num_bytes -= 2;
+}
+
+void on_write_ftdi(usb_serial_device *usd, const char *buf,
+ size_t *num_bytes){
+ char *buf_to = usd->write_buffer;
+ int hdrlen = usd->spec.ftdi.hdrlen;
+ TRACE("hdrlen:%d\n", hdrlen);
+ if(*num_bytes > usd->write_buffer_size - hdrlen)
+ *num_bytes = usd->write_buffer_size - hdrlen;
+ if(hdrlen > 0)
+ *buf_to = FTDI_OUT_TAG(*num_bytes, FTDI_PIT_DEFAULT);
+ memcpy(buf_to + hdrlen, buf, *num_bytes);
+ *num_bytes += hdrlen;
+}
+
+void on_close_ftdi(usb_serial_device *usd){
+ TRACE_FUNCALLS("> on_close_ftdi(%08x)\n", usd);
+ (*usb_m->cancel_queued_transfers)(usd->pipe_read);
+ (*usb_m->cancel_queued_transfers)(usd->pipe_write);
+}
+
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h
new file mode 100644
index 0000000000..5f80bb1c48
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/ftdi.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USB_FTDI_H_
+ #define _USB_FTDI_H_
+
+#define VND_FTDI 0x0403
+
+#define PROD_8U100AX 0x8372
+#define PROD_8U232AM 0x6001
+
+#define FTDI_BUF_SIZE 0x40
+
+status_t add_ftdi_device(usb_serial_device *usd,
+ const usb_configuration_info *uci);
+status_t reset_ftdi_device(usb_serial_device *usd);
+status_t set_line_coding_ftdi(usb_serial_device *usd,
+ usb_serial_line_coding *line_coding);
+status_t set_control_line_state_ftdi(usb_serial_device *usd, uint16 state);
+void on_read_ftdi(usb_serial_device *usd, char **buf, size_t *num_bytes);
+void on_write_ftdi(usb_serial_device *usd, const char *buf, size_t *num_bytes);
+void on_close_ftdi(usb_serial_device *usd);
+
+#endif //_USB_FTDI_H_
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/install.sh b/src/add-ons/kernel/drivers/ports/usb_serial/install.sh
new file mode 100755
index 0000000000..b373eba71c
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/install.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+DRIVER_TITLE="USB Serial"
+DRIVER_NAME=usb_serial
+
+answer=`alert "Do you really want to install the $DRIVER_TITLE driver?" "No" "Yes"`
+if [ $answer == "No" ]; then
+ exit
+fi
+
+/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/
+/boot/beos/bin/install -d ~/config/settings/kernel/drivers/
+/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/ports/
+/boot/beos/bin/install `dirname $0`/$DRIVER_NAME ~/config/add-ons/kernel/drivers/bin/
+/boot/beos/bin/cp `dirname $0`/$DRIVER_NAME.settings.sample ~/config/settings/kernel/drivers/$DRIVER_NAME
+
+mimeset ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME
+mimeset ~/config/settings/kernel/drivers/$DRIVER_NAME
+
+ln -sf ../../bin/$DRIVER_NAME ~/config/add-ons/kernel/drivers/dev/ports/$DRIVER_NAME
+
+rescan $DRIVER_NAME
+
+alert "The $DRIVER_TITLE driver has been installed in your system."
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c
new file mode 100644
index 0000000000..823963d164
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+#include "driver.h"
+#include "prolific.h"
+
+status_t add_prolific_device(usb_serial_device *usd,
+ const usb_configuration_info *uci)
+{
+ struct usb_endpoint_info *comm_epi = NULL;
+ struct usb_endpoint_info *data_out_epi = NULL;
+ struct usb_endpoint_info *data_in_epi = NULL;
+ status_t status = ENODEV;
+ int i = 0;
+
+ TRACE_FUNCALLS("> add_prolific_device(%08x, %08x)\n", usd, uci);
+
+ if(uci->interface_count){
+ struct usb_interface_info *uii = uci->interface[0].active;
+ for(i = 0; i < uii->endpoint_count; i++){
+ if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_INTERRUPT){
+ if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
+ == USB_EP_ADDR_DIR_IN) /*USB_EP_ADDR_DIR_OUT = 0x0*/
+ comm_epi = &uii->endpoint[i];
+ }
+ }
+ /*They say that USB-RSAQ1 has 2 interfaces */
+ if(uci->interface_count == 2){
+ uii = uci->interface[1].active;
+ }
+
+ for(i = 0; i < uii->endpoint_count; i++){
+ if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_BULK){
+ if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN)
+ == USB_EP_ADDR_DIR_IN){
+ data_in_epi = &uii->endpoint[i];
+ }else{
+ if(uii->endpoint[i].descr->endpoint_address
+ /*USB_EP_ADDR_DIR_OUT = 0x0*/){
+ data_out_epi = &uii->endpoint[i];
+ }
+ }
+ }
+ }
+
+ if(comm_epi && data_in_epi && data_out_epi){
+ usd->read_buffer_size =
+ usd->write_buffer_size =
+ usd->interrupt_buffer_size = ROUNDUP(PROLIFIC_BUF_SIZE, 16);
+ status = add_device(usd, uci, comm_epi, data_out_epi, data_in_epi);
+ }
+ }
+
+ TRACE_FUNCRET("< add_prolific_device returns:%08x\n", status);
+ return status;
+}
+
+status_t reset_prolific_device(usb_serial_device *usd){
+ status_t status;
+ size_t len = 0;
+ TRACE_FUNCALLS("> reset_prolific_device(%08x)\n", usd);
+ status = (*usb_m->send_request)(usd->dev,
+ USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT,
+ PROLIFIC_SET_REQUEST, 0, 0, 0, 0, 0, &len);
+ TRACE_FUNCRET("< reset_prolific_device returns:%08x\n", status);
+ return status;
+}
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h
new file mode 100644
index 0000000000..10e86ab193
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/prolific.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2003-2004 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USB_PROLIFIC_H_
+ #define _USB_PROLIFIC_H_
+
+#define VND_PROLIFIC 0x067b
+#define VND_IODATA 0x04bb
+#define VND_ATEN 0x0557
+#define VND_TDK 0x04bf
+#define VND_RATOC 0x0584
+#define VND_ELECOM 0x056e
+#define VND_SOURCENEXT 0x0833
+#define VND_HAL 0x0b41
+
+#define PROD_IODATA_USBRSAQ 0x0a03
+#define PROD_PROLIFIC_RSAQ2 0x04bb
+#define PROD_ATEN_UC232A 0x2008
+#define PROD_PROLIFIC_PL2303 0x2303
+#define PROD_TDK_UHA6400 0x0117
+#define PROD_RATOC_REXUSB60 0xb000
+#define PROD_ELECOM_UCSGT 0x5003
+#define PROD_SOURCENEXT_KEIKAI8 0x039f
+#define PROD_SOURCENEXT_KEIKAI8_CHG 0x012e
+#define PROD_HAL_IMR001 0x0011
+
+// dobavit?!!!!!!!!!!!!!
+// { 0, 0, 0, 0x0eba, 0x1080 }, // ITEGNO
+// { 0, 0, 0, 0x0df7, 0x2620 } // MA620
+
+#define PROLIFIC_SET_REQUEST 0x01
+
+#define PROLIFIC_BUF_SIZE 0x100
+
+status_t add_prolific_device(usb_serial_device *usd,
+ const usb_configuration_info *uci);
+status_t reset_prolific_device(usb_serial_device *usd);
+
+#endif //_USB_PROLIFIC_H_
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c
new file mode 100644
index 0000000000..33075b1a3c
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+
+#include //sprintf
+#include //posix file i/o - create, write, close
+#include
+
+
+#include "driver.h"
+//#include "dano_hack.h"
+
+#if DEBUG
+bool b_log = true;
+#else
+bool b_log = false;
+#endif
+bool b_log_file = false;
+bool b_log_append = false;
+bool b_log_funcalls = false;
+bool b_log_funcret = false;
+bool b_log_funcres = false;
+bool b_acm_support = true;
+
+static const char *private_log_path="/boot/home/"DRIVER_NAME".log";
+static sem_id loglock;
+
+void load_setting(){
+ void *settingshandle;
+ settingshandle = load_driver_settings(DRIVER_NAME);
+#if !DEBUG
+ b_log = get_driver_boolean_parameter(
+ settingshandle, "debug_output", b_log, true);
+#endif
+ b_log_file = get_driver_boolean_parameter(
+ settingshandle, "debug_output_in_file", b_log_file, true);
+ b_log_append = ! get_driver_boolean_parameter(
+ settingshandle, "debug_output_file_rewrite", !b_log_append, true);
+ b_log_funcalls = get_driver_boolean_parameter(
+ settingshandle, "debug_trace_func_calls", b_log_funcalls, false);
+ b_log_funcret = get_driver_boolean_parameter(
+ settingshandle, "debug_trace_func_returns", b_log_funcret, false);
+ b_log_funcres = get_driver_boolean_parameter(
+ settingshandle, "debug_trace_func_results", b_log_funcres, false);
+ b_acm_support = get_driver_boolean_parameter(
+ settingshandle, "support_acm_devices", b_acm_support, true);
+
+ unload_driver_settings(settingshandle);
+}
+
+void create_log(){
+ int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0);
+ if(!b_log_file)
+ return;
+ close(open(private_log_path, flags, 0666));
+ loglock = create_sem(1, DRIVER_NAME"-logging");
+}
+
+void usb_serial_trace(bool b_force, char *fmt, ...){
+ if(!(b_force || b_log))
+ return;
+ {
+ va_list arg_list;
+ static char *prefix = "\33[32m"DRIVER_NAME":\33[0m";
+ static char buf[1024];
+ char *buf_ptr = buf;
+ if(!b_log_file){
+ strcpy(buf, prefix);
+ buf_ptr += strlen(prefix);
+ }
+
+ va_start(arg_list, fmt);
+ vsprintf(buf_ptr, fmt, arg_list);
+ va_end(arg_list);
+
+ if(b_log_file){
+ int fd;
+ acquire_sem(loglock);
+ fd = open(private_log_path, O_WRONLY | O_APPEND);
+ write(fd, buf, strlen(buf));
+ close(fd);
+ release_sem(loglock);
+ }
+ else
+ dprintf(buf);
+ }
+}
+
+void trace_ddomain(struct ddomain *dd){
+ TRACE("struct ddomain\n"
+ " ddrover: %08x\n"
+ " bg:%d, locked:%d\n", dd->r, dd->bg, dd->locked);
+}
+
+void trace_termios(struct termios *tios){
+ TRACE("struct termios\n"
+ " c_iflag:%08x\n"
+ " c_oflag:%08x\n"
+ " c_cflag:%08x\n"
+ " c_lflag:%08x\n"
+ " c_line: %08x\n"
+ " c_ixxxxx:%08x\n"
+ " c_oxxxxx:%08x\n"
+ " c_cc [%02x, %02x, %02x, %02x, %02x, %02x, "
+ "%02x, %02x, %02x, %02x, %02x]\n",
+ tios->c_iflag, tios->c_oflag, tios->c_cflag, tios->c_lflag,
+ tios->c_line, tios->c_ixxxxx, tios->c_oxxxxx,
+ tios->c_cc[0], tios->c_cc[1], tios->c_cc[2], tios->c_cc[3],
+ tios->c_cc[4], tios->c_cc[5], tios->c_cc[6], tios->c_cc[7],
+ tios->c_cc[8], tios->c_cc[9], tios->c_cc[10]);
+}
+
+void trace_str(struct str *str){
+ TRACE("struct str\n"
+ " buffer:%08x\n"
+ " bufsize:%d\n"
+ " count:%d\n"
+ " tail:%d\n"
+ " allocated: %d\n",
+ str->buffer,
+ str->bufsize, str->count, str->tail,
+ str->allocated);
+}
+
+void trace_winsize(struct winsize *ws){
+ TRACE("struct winsize\n"
+ " ws_row:%d\n"
+ " ws_col:%d\n"
+ " ws_xpixel:%d\n"
+ " ws_ypixel:%d\n",
+ ws->ws_row, ws->ws_col, ws->ws_xpixel, ws->ws_ypixel);
+}
+
+void trace_tty(struct tty *tty){
+ TRACE("\n>> STRUCT tty\n"
+ " nopen:%d, flags:%08x,\n",
+ tty->nopen, tty->flags);
+
+ TRACE("\n ddomain dd:\n");
+ trace_ddomain(&tty->dd);
+ TRACE("\n ddomain ddi:\n");
+ trace_ddomain(&tty->ddi);
+
+ TRACE(" pgid: %08x\n", tty->pgid);
+
+ TRACE("\n termios t:");
+ trace_termios(&tty->t);
+
+ TRACE(" iactivity: %d, ibusy:%d\n", tty->iactivity, tty->ibusy);
+
+ TRACE("\n str istr:\n");
+ trace_str(&tty->istr);
+ TRACE("\n str rstr:\n");
+ trace_str(&tty->rstr);
+ TRACE("\n str ostr:\n");
+ trace_str(&tty->ostr);
+
+ TRACE("\n winsize wsize:\n");
+ trace_winsize(&tty->wsize);
+
+ TRACE(" service: %08x\n", tty->service);
+ TRACE("\n<< STRUCT tty\n");
+}
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h
new file mode 100644
index 0000000000..e15ab9ee67
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/tracing.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USB_SERIAL_TRACING_H_
+ #define _USB_SERIAL_TRACING_H_
+
+void load_setting();
+void create_log();
+void usb_serial_trace(bool b_force, char *fmt, ...);
+
+#define TRACE_ALWAYS(x...) usb_serial_trace(true, x);
+#define TRACE(x...) usb_serial_trace(false, x);
+
+extern bool b_log_funcalls;
+#define TRACE_FUNCALLS(x...)\
+ { if(b_log_funcalls) usb_serial_trace(false, x);}
+
+extern bool b_log_funcret;
+#define TRACE_FUNCRET(x...)\
+ { if(b_log_funcret) usb_serial_trace(false, x);}
+
+extern bool b_log_funcres;
+#define TRACE_FUNCRES(func, param)\
+ { if(b_log_funcres) func(param);}
+
+void trace_ddomain(struct ddomain *dd);
+void trace_termios(struct termios *tios);
+void trace_str(struct str *str);
+void trace_winsize(struct winsize *ws);
+void trace_tty(struct tty *tty);
+
+extern bool b_acm_support;
+
+#endif//_USB_SERIAL_TRACING_H_
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h b/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h
new file mode 100644
index 0000000000..04586e8030
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/uftdireg.h
@@ -0,0 +1,358 @@
+/* $NetBSD: uftdireg.h,v 1.6 2002/07/11 21:14:28 augustss Exp $ */
+/* $FreeBSD: src/sys/dev/usb/uftdireg.h,v 1.1 2002/08/11 23:32:33 joe Exp $ */
+
+/*
+ * Definitions for the FTDI USB Single Port Serial Converter -
+ * known as FTDI_SIO (Serial Input/Output application of the chipset)
+ *
+ * The device is based on the FTDI FT8U100AX chip. It has a DB25 on one side,
+ * USB on the other.
+ *
+ * Thanx to FTDI (http://www.ftdi.co.uk) for so kindly providing details
+ * of the protocol required to talk to the device and ongoing assistence
+ * during development.
+ *
+ * Bill Ryder - bryder@sgi.com of Silicon Graphics, Inc. is the original
+ * author of this file.
+ */
+/* Modified by Lennart Augustsson */
+
+/*
+ * Added to BeOS USB Serial Driver project by Siarzhuk Zharski
+ *
+ * $Source: /cvsroot/sis4be/usb_serial/uftdireg.h,v $
+ * $Author: zharik $
+ * $Revision: 1.1 $
+ * $Date: 2003/05/29 18:55:43 $
+ *
+ */
+
+/* Vendor Request Interface */
+#define FTDI_SIO_RESET 0 /* Reset the port */
+#define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */
+#define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */
+#define FTDI_SIO_SET_BAUD_RATE 3 /* Set baud rate */
+#define FTDI_SIO_SET_DATA 4 /* Set the data characteristics of the port */
+#define FTDI_SIO_GET_STATUS 5 /* Retrieve current value of status reg */
+#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
+#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
+
+/* Port Identifier Table */
+#define FTDI_PIT_DEFAULT 0 /* SIOA */
+#define FTDI_PIT_SIOA 1 /* SIOA */
+#define FTDI_PIT_SIOB 2 /* SIOB */
+#define FTDI_PIT_PARALLEL 3 /* Parallel */
+
+enum uftdi_type {
+ UFTDI_TYPE_SIO,
+ UFTDI_TYPE_8U232AM
+};
+
+/*
+ * BmRequestType: 0100 0000B
+ * bRequest: FTDI_SIO_RESET
+ * wValue: Control Value
+ * 0 = Reset SIO
+ * 1 = Purge RX buffer
+ * 2 = Purge TX buffer
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ *
+ * The Reset SIO command has this effect:
+ *
+ * Sets flow control set to 'none'
+ * Event char = 0x0d
+ * Event trigger = disabled
+ * Purge RX buffer
+ * Purge TX buffer
+ * Clear DTR
+ * Clear RTS
+ * baud and data format not reset
+ *
+ * The Purge RX and TX buffer commands affect nothing except the buffers
+ *
+ */
+/* FTDI_SIO_RESET */
+#define FTDI_SIO_RESET_SIO 0
+#define FTDI_SIO_RESET_PURGE_RX 1
+#define FTDI_SIO_RESET_PURGE_TX 2
+
+
+/*
+ * BmRequestType: 0100 0000B
+ * bRequest: FTDI_SIO_SET_BAUDRATE
+ * wValue: BaudRate value - see below
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ */
+/* FTDI_SIO_SET_BAUDRATE */
+enum {
+ ftdi_sio_b300 = 0,
+ ftdi_sio_b600 = 1,
+ ftdi_sio_b1200 = 2,
+ ftdi_sio_b2400 = 3,
+ ftdi_sio_b4800 = 4,
+ ftdi_sio_b9600 = 5,
+ ftdi_sio_b19200 = 6,
+ ftdi_sio_b38400 = 7,
+ ftdi_sio_b57600 = 8,
+ ftdi_sio_b115200 = 9
+};
+
+enum {
+ ftdi_8u232am_b300 = 0x2710,
+ ftdi_8u232am_b600 = 0x1388,
+ ftdi_8u232am_b1200 = 0x09c4,
+ ftdi_8u232am_b2400 = 0x04e2,
+ ftdi_8u232am_b4800 = 0x0271,
+ ftdi_8u232am_b9600 = 0x4138,
+ ftdi_8u232am_b19200 = 0x809c,
+ ftdi_8u232am_b38400 = 0xc04e,
+ ftdi_8u232am_b57600 = 0x0034,
+ ftdi_8u232am_b115200 = 0x001a,
+ ftdi_8u232am_b230400 = 0x000d,
+ ftdi_8u232am_b460800 = 0x4006,
+ ftdi_8u232am_b921600 = 0x8003
+};
+
+/*
+ * BmRequestType: 0100 0000B
+ * bRequest: FTDI_SIO_SET_DATA
+ * wValue: Data characteristics (see below)
+ * wIndex: Port
+ * wLength: 0
+ * Data: No
+ *
+ * Data characteristics
+ *
+ * B0..7 Number of data bits
+ * B8..10 Parity
+ * 0 = None
+ * 1 = Odd
+ * 2 = Even
+ * 3 = Mark
+ * 4 = Space
+ * B11..13 Stop Bits
+ * 0 = 1
+ * 1 = 1.5
+ * 2 = 2
+ * B14..15 Reserved
+ *
+ */
+/* FTDI_SIO_SET_DATA */
+#define FTDI_SIO_SET_DATA_BITS(n) (n)
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8)
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8)
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11)
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11)
+#define FTDI_SIO_SET_BREAK (0x1 << 14)
+
+
+/*
+ * BmRequestType: 0100 0000B
+ * bRequest: FTDI_SIO_MODEM_CTRL
+ * wValue: ControlValue (see below)
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ *
+ * NOTE: If the device is in RTS/CTS flow control, the RTS set by this
+ * command will be IGNORED without an error being returned
+ * Also - you can not set DTR and RTS with one control message
+ *
+ * ControlValue
+ * B0 DTR state
+ * 0 = reset
+ * 1 = set
+ * B1 RTS state
+ * 0 = reset
+ * 1 = set
+ * B2..7 Reserved
+ * B8 DTR state enable
+ * 0 = ignore
+ * 1 = use DTR state
+ * B9 RTS state enable
+ * 0 = ignore
+ * 1 = use RTS state
+ * B10..15 Reserved
+ */
+/* FTDI_SIO_MODEM_CTRL */
+#define FTDI_SIO_SET_DTR_MASK 0x1
+#define FTDI_SIO_SET_DTR_HIGH (1 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_DTR_LOW (0 | ( FTDI_SIO_SET_DTR_MASK << 8))
+#define FTDI_SIO_SET_RTS_MASK 0x2
+#define FTDI_SIO_SET_RTS_HIGH (2 | ( FTDI_SIO_SET_RTS_MASK << 8))
+#define FTDI_SIO_SET_RTS_LOW (0 | ( FTDI_SIO_SET_RTS_MASK << 8))
+
+
+/*
+ * BmRequestType: 0100 0000b
+ * bRequest: FTDI_SIO_SET_FLOW_CTRL
+ * wValue: Xoff/Xon
+ * wIndex: Protocol/Port - hIndex is protocl / lIndex is port
+ * wLength: 0
+ * Data: None
+ *
+ * hIndex protocol is:
+ * B0 Output handshaking using RTS/CTS
+ * 0 = disabled
+ * 1 = enabled
+ * B1 Output handshaking using DTR/DSR
+ * 0 = disabled
+ * 1 = enabled
+ * B2 Xon/Xoff handshaking
+ * 0 = disabled
+ * 1 = enabled
+ *
+ * A value of zero in the hIndex field disables handshaking
+ *
+ * If Xon/Xoff handshaking is specified, the hValue field should contain the
+ * XOFF character and the lValue field contains the XON character.
+ */
+/* FTDI_SIO_SET_FLOW_CTRL */
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0
+#define FTDI_SIO_RTS_CTS_HS 0x1
+#define FTDI_SIO_DTR_DSR_HS 0x2
+#define FTDI_SIO_XON_XOFF_HS 0x4
+
+
+/*
+ * BmRequestType: 0100 0000b
+ * bRequest: FTDI_SIO_SET_EVENT_CHAR
+ * wValue: Event Char
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ *
+ * wValue:
+ * B0..7 Event Character
+ * B8 Event Character Processing
+ * 0 = disabled
+ * 1 = enabled
+ * B9..15 Reserved
+ *
+ * FTDI_SIO_SET_EVENT_CHAR
+ *
+ * Set the special event character for the specified communications port.
+ * If the device sees this character it will immediately return the
+ * data read so far - rather than wait 40ms or until 62 bytes are read
+ * which is what normally happens.
+ */
+
+
+
+/*
+ * BmRequestType: 0100 0000b
+ * bRequest: FTDI_SIO_SET_ERROR_CHAR
+ * wValue: Error Char
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ *
+ * Error Char
+ * B0..7 Error Character
+ * B8 Error Character Processing
+ * 0 = disabled
+ * 1 = enabled
+ * B9..15 Reserved
+ *
+ *
+ * FTDI_SIO_SET_ERROR_CHAR
+ * Set the parity error replacement character for the specified communications
+ * port.
+ */
+
+
+/*
+ * BmRequestType: 1100 0000b
+ * bRequest: FTDI_SIO_GET_MODEM_STATUS
+ * wValue: zero
+ * wIndex: Port
+ * wLength: 1
+ * Data: Status
+ *
+ * One byte of data is returned
+ * B0..3 0
+ * B4 CTS
+ * 0 = inactive
+ * 1 = active
+ * B5 DSR
+ * 0 = inactive
+ * 1 = active
+ * B6 Ring Indicator (RI)
+ * 0 = inactive
+ * 1 = active
+ * B7 Receive Line Signal Detect (RLSD)
+ * 0 = inactive
+ * 1 = active
+ *
+ * FTDI_SIO_GET_MODEM_STATUS
+ * Retrieve the current value of the modem status register.
+ */
+#define FTDI_SIO_CTS_MASK 0x10
+#define FTDI_SIO_DSR_MASK 0x20
+#define FTDI_SIO_RI_MASK 0x40
+#define FTDI_SIO_RLSD_MASK 0x80
+
+
+
+/*
+ *
+ * DATA FORMAT
+ *
+ * IN Endpoint
+ *
+ * The device reserves the first two bytes of data on this endpoint to contain
+ * the current values of the modem and line status registers. In the absence of
+ * data, the device generates a message consisting of these two status bytes
+ * every 40 ms.
+ *
+ * Byte 0: Modem Status
+ * NOTE: 4 upper bits have same layout as the MSR register in a 16550
+ *
+ * Offset Description
+ * B0..3 Port
+ * B4 Clear to Send (CTS)
+ * B5 Data Set Ready (DSR)
+ * B6 Ring Indicator (RI)
+ * B7 Receive Line Signal Detect (RLSD)
+ *
+ * Byte 1: Line Status
+ * NOTE: same layout as the LSR register in a 16550
+ *
+ * Offset Description
+ * B0 Data Ready (DR)
+ * B1 Overrun Error (OE)
+ * B2 Parity Error (PE)
+ * B3 Framing Error (FE)
+ * B4 Break Interrupt (BI)
+ * B5 Transmitter Holding Register (THRE)
+ * B6 Transmitter Empty (TEMT)
+ * B7 Error in RCVR FIFO
+ *
+ *
+ * OUT Endpoint
+ *
+ * This device reserves the first bytes of data on this endpoint contain the
+ * length and port identifier of the message. For the FTDI USB Serial converter
+ * the port identifier is always 1.
+ *
+ * Byte 0: Port & length
+ *
+ * Offset Description
+ * B0..1 Port
+ * B2..7 Length of message - (not including Byte 0)
+ *
+ */
+#define FTDI_PORT_MASK 0x0f
+#define FTDI_MSR_MASK 0xf0
+#define FTDI_GET_MSR(p) (((p)[0]) & FTDI_MSR_MASK)
+#define FTDI_GET_LSR(p) ((p)[1])
+#define FTDI_LSR_MASK (~0x60) /* interesting bits */
+#define FTDI_OUT_TAG(len, port) (((len) << 2) | (port))
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh b/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh
new file mode 100755
index 0000000000..351b914a64
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/uninstall.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+DRIVER_TITLE="USB Serial"
+DRIVER_NAME=usb_serial
+
+answer=`alert "Do you really want to uninstall the $DRIVER_TITLE driver?" "No" "Yes"`
+if [ $answer == "No" ]; then
+ exit
+fi
+
+rm ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME
+rm ~/config/settings/kernel/drivers/$DRIVER_NAME
+rm ~/config/add-ons/kernel/drivers/dev/ports/$DRIVER_NAME
+
+rescan $DRIVER_NAME
+
+alert "The $DRIVER_TITLE driver has been removed from your system."
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef
new file mode 100644
index 0000000000..5e16be8d69
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.rdef
@@ -0,0 +1,54 @@
+resource(1, "BEOS:L:STD_ICON") #'ICON' array {
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF0000FFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF0000FFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFF00FFFFFF0000FFFFFFFF0000FFFFFFFFFFFFFF00"
+ $"FFFFFFFFFFFFFFFFFFFFFF001C00000000FFFFFFFF0000FFFFFFFFFFFFFF0000"
+ $"FFFFFFFFFFFFFFFFFFFF001B1818180000FFFFFF0000FFFFFFFF000000000000"
+ $"FFFFFFFFFFFFFFFFFF001B183F3F3F181800000000FFFFFFFF001C1C1C000000"
+ $"FFFFFFFFFFFFFFFF001B180F0F0F0F0F1818180000FFFFFF001C1818181800FF"
+ $"FFFFFFFFFFFFFF001C1818181818181818181818180000001C181818183F00FF"
+ $"FFFFFFFFFFFF001C18181818181818181818181818181800001818183F0F00FF"
+ $"FFFFFFFFFF001B18181818181818181818181818181818181800003F0F0F00FF"
+ $"FFFFFFFF001C181818181818181818181818181818181818181818000000FFFF"
+ $"FFFFFF001C181818181818181818181818181818181818181818183F0E00FFFF"
+ $"FFFF001B181818181818181818181818181818181818181818183F0F0F00FFFF"
+ $"FF001C181818181818181818181818181818181818181818183F0F0F0F00FFFF"
+ $"000E181818181818181818181818181818181818181818183F0F0F0F0F00FFFF"
+ $"003F3F1818183F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F183F0F0F0F0F0F00FFFF"
+ $"0017173F3F18180F0F0F0F0F0F0F0F0F0F0F0F0F0F183F0F0F0F0F0F0F000FFF"
+ $"00202018173F3F1818183F3F3F3F3F3F3F3F3F3F183F0F0F0F0F0F0F000E0EFF"
+ $"001717202017183F3F18180F0F0F0F0F0F0F0F183F0F0F0F0F0F0F000F0F0FFF"
+ $"00182A1817202017183F3F1818183F3F3F18183F0F0F0F0F0F0F000F0F0FFFFF"
+ $"002A2A182E1817171718173F3F18180F0F183F0F0F0F0F0F0F000F0F0FFFFFFF"
+ $"0017182E2E182E1818171718173F3F18183F0F0F0F0F0F0F000F0F0FFFFFFFFF"
+ $"FF000017182E2E182A1718171718173F3F0F0F0F0F0F0F000F0F0FFFFFFFFFFF"
+ $"FFFFFF000017172A2A182E171817171C170F0F0F0F0F000F0F0FFFFFFFFFFFFF"
+ $"FFFFFFFFFF000017172E2E182A17181B180E0F0F0F000F0F0FFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFF000017172A2A18341B180F0F0E000F0F0FFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFF0000171734341C170F0F000F0F0EFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFF000017171C170F000F0F0FFFFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFF00001B18000E0F0FFFFFFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000E0F0FFFFFFFFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+};
+
+resource(1, "BEOS:M:STD_ICON") #'MICN' array {
+ $"FFFFFFFFFFFFFFFFFF00FFFF00FFFFFF"
+ $"FFFFFFFFFFFF09FF00FFFF00FFFFFF00"
+ $"FFFFFFFFFF131B1308FF00FFFF0E0700"
+ $"FFFFFFFF13151313181208FF141819FF"
+ $"FFFFFF1318181818181818120C1313FF"
+ $"FFFF14181818181818181818181303FF"
+ $"FF1318181818181818181818191307FF"
+ $"0B19181B1B1B1B1B1B1B1B19130F07FF"
+ $"D5871B1713171717171717130F0F07FF"
+ $"0BA8AD871B1713171517130F0F070FFF"
+ $"D0A3A91317191B1717130F0F070FFFFF"
+ $"FF07A9A3A313171A150F0F070FFFFFFF"
+ $"FFFFFF07A9A3A368130E070FFFFFFFFF"
+ $"FFFFFFFFFF078F6813070FFFFFFFFFFF"
+ $"FFFFFFFFFFFFFF09090EFFFFFFFFFFFF"
+ $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+};
+
diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample
new file mode 100644
index 0000000000..2e008c263d
--- /dev/null
+++ b/src/add-ons/kernel/drivers/ports/usb_serial/usb_serial.settings.sample
@@ -0,0 +1,37 @@
+#
+# The sample USB serial driver settings file
+#
+# Rename it to usb_serial and put into
+# /boot/home/config/settings/kernel/drivers/
+# After restarting your system the new settings will works.
+
+#support_acm_devices - if you have other ACM driver in your system you can disable
+# ACM support by setting this key to "false". The default value is "true" - the ACM
+# support is activated.
+#support_acm_devices true
+
+# Following settings are for debugging purposes.
+# Debug output - this is a possibility to view some kind of development related
+# information - error and warning messages etc.
+
+# debug_output - activates debug output. The debug builds has debug output
+# activated by default and this key has no effect on it. The release builds requires
+# to activate this if you want to see debug messages in syslog or in private log file.
+#
+# debug_output true
+
+# debug_output_in_file - activates writing of debug messages into private log file.
+# The name of this file is /boot/home/usb_serial.log. If this key is set to true - no messages
+# will be written into syslog.
+#
+# debug_output_in_file true
+
+# debug_output_file_rewrite - activates rewriting of private log file on
+# calling driver_init() syscall. By default this set in false.
+#
+# debug_output_file_rewrite false
+
+# debug_trace_func_calls - the information about driver functions calls
+# will be traced. Would you like to see internals? Then activate this.
+#
+# debug_trace_func_calls true
diff --git a/src/add-ons/kernel/drivers/video/Jamfile b/src/add-ons/kernel/drivers/video/Jamfile
new file mode 100644
index 0000000000..9c40f09ee8
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/Jamfile
@@ -0,0 +1,3 @@
+SubDir HAIKU_TOP src add-ons kernel drivers video ;
+
+SubInclude HAIKU_TOP src add-ons kernel drivers video usb_vision ;
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/Jamfile b/src/add-ons/kernel/drivers/video/usb_vision/Jamfile
new file mode 100644
index 0000000000..81e259797c
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/Jamfile
@@ -0,0 +1,24 @@
+SubDir HAIKU_TOP src add-ons kernel drivers video ;
+
+SetSubDirSupportedPlatformsBeOSCompatible ;
+
+UsePrivateHeaders usb_vision ;
+
+#local defines = [ FDefines DB_USB_USE_V2_MODULE ] ;
+#SubDirCcFlags $(defines) ;
+
+KernelAddon usb_vision : kernel drivers bin :
+ usb_vision.c
+ tracing.c
+;
+
+# driver goes in dev/video
+
+Package haiku-usb_vision-cvs
+ :
+ usb_vision
+ :
+ boot home config add-ons kernel drivers bin ;
+
+Package haiku-usb_vision-cvs : usb_vision.settings.sample
+ : boot home config settings kernel drivers sample ;
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html b/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html
new file mode 100644
index 0000000000..40716c245b
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/ReadMe.html
@@ -0,0 +1,240 @@
+
+BeOS driver for USBVision (Nogatech) TV tuners
+
+BeOS driver for USBVision (Nogatech) TV tuners
+
+Introduction
+This driver is designed to support USBVision (Nogatech) TV Tuners. Tested with:
+
+
+| Name | Vendor ID | Product ID |
+
+| Hauppauge WinTV FM | 0x0573 | 0x4d31 |
+
+
+|
+NOTE that
+ |
+I have one small request for you - if you tried this driver and it works -
+PLEASE e-mail me the information about your USB TV Tuner and results of your
+experiments. This information is very interesting for me and helps in improvement
+this driver! Thank you for co-operation!
+ |
|
+NOTE that
+ |
+If you definetily have the some kind of USB TV Tuner but this driver didn't
+help you - see section "Unknown devices" below for instructions.
+ |
+
+|
+NOTE that
+ |
+If your computer has the OHCI-compatible USB hardware you are out of luck. This hardware is not
+supported by non-Dan0-like versions. See the BeOS.USB.patches vor details and
+solutions.
+ |
+
+What's new:
+|
+Version:
+ |
+History:
+ |
|
+0.1.0-dev-0
+ |
+very first "development" release.
+ |
+
+
+1. Installation
+
+- Run install.sh
+
- If all is OK ... //TODO:
+
- If something goes wrong ... //TODO:
+
+2. Uninstallation
+
+
+3. Problems solving
+
+- If this driver crash your system - reboot and press "Space" during load. In boot menu select
+ "Disable user add-ons" and continue boot. Uninstall driver and reboot again into normal mode.
+ Write me a e-mail about this problem.
+
+4. "Unknown" devices
+
+ If you have something, that looks like USB TV tuner and tried it with
+ this driver but have no success - download
+ usb device info tool and use it to get required information.
+
+- Unplug all USB devices and hubs from your PC.
+
- Go into Terminal and run the following command:
+ ls -alR /dev/bus/usb
+ You should see something like this:
+
+$ ls -alR /dev/bus/usb/
+/dev/bus/usb:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 Jun 1 2003 ..
+drw-r--r-- 1 walther users 0 May 31 23:16 0
+drw-r--r-- 1 walther users 0 May 31 23:16 1
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 unload
+
+/dev/bus/usb/0:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+/dev/bus/usb/1:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+
+ - Note this information.
+
- Now plug your USB TV tuner into PC and run ls -alR /dev/bus/usb/ again.
+You'll get something slightly different:
+
+$ ls -alR /dev/bus/usb/
+/dev/bus/usb:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 Jun 1 2003 ..
+drw-r--r-- 1 walther users 0 May 31 23:16 0
+drw-r--r-- 1 walther users 0 May 31 23:16 1
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 unload
+
+/dev/bus/usb/0:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+/dev/bus/usb/1:
+total 0
+drw-r--r-- 1 walther users 0 May 31 23:16 .
+drw-r--r-- 1 walther users 0 May 31 23:16 ..
+crw-r--r-- 1 walther users 0, 0 May 31 23:16 hub
+
+
+$
+ - Compare this results with previous one and look for file,
+that appeared. This file is your USB TV tuner.
+
- Unpack downloaded usb_dev_info command and run it with full path to file appeared in
+the second listing. For my sample I should run:
+usb_dev_info /dev/bus/usb/0/1
+I'll get the following:
+
+$ usb_dev_info /dev/bus/usb/0/1
+[Device]
+Class .................. 0
+Subclass ............... 0
+Protocol ............... 0
+Vendor ID .............. 0x0573
+Product ID ............. 0x4d31
+Version ................ 0x0100
+Manufacturer String .... "NT"
+Product String ......... ""
+Serial Number .......... ""
+ [Configuration 0]
+ [Interface 0]
+ Class .............. 0
+ Subclass ........... 0
+ Protocol ........... 0
+ [Endpoint 0]
+ MaxPacketSize .... 8
+ Interval ......... 1
+ Direction ........ Input
+ [Endpoint 1]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Output
+ [Configuration 1]
+ [Interface 0]
+ Class .............. 0
+ Subclass ........... 0
+ Protocol ........... 0
+ [Endpoint 0]
+ MaxPacketSize .... 8
+ Interval ......... 1
+ Direction ........ Input
+ [Endpoint 1]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Output
+ [Endpoint 2]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Input
+ [Configuration 2]
+ [Interface 0]
+ Class .............. 0
+ Subclass ........... 0
+ Protocol ........... 0
+ [Endpoint 0]
+ MaxPacketSize .... 8
+ Interval ......... 1
+ Direction ........ Input
+ [Endpoint 1]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Output
+ [Endpoint 2]
+ MaxPacketSize .... 64
+ Interval ......... 1
+ Type ............. Bulk
+ Direction ........ Output
+ [Configuration 3]
+ [Interface 0]
+ Class .............. 0
+ Subclass ........... 0
+ Protocol ........... 0
+ [Endpoint 0]
+ MaxPacketSize .... 8
+ Interval ......... 1
+ Direction ........ Input
+ [Endpoint 1]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Output
+ [Endpoint 2]
+ MaxPacketSize .... 0
+ Interval ......... 1
+ Type ............. Isochronous
+ Direction ........ Input
+ [Endpoint 3]
+ MaxPacketSize .... 64
+ Interval ......... 1
+ Type ............. Bulk
+ Direction ........ Output
+
+ - Send this information to me with some additional words about your device.
+
+
+What is "BeOS.USB.patches"?
+
+All know that "classical" BeOS R5 don't works on OHCI USB hardware. But some time ago on one well-known
+BeOS file-sharing network appeared patches for plain R5. Those patches allows to work with OHCI
+hardware under this system version. Looks like it is some part of Dan0 or other "leaked" versions.
+There are 3 patches in BeOS.USB.patches.zip:
+1. beos-usb-patch,
+
2. beos-usb.modem-patch,
+
3. beos-usb.modem-patch.sm.
+
You need the first one to make your OHCI hardware working under R5. Install it and proceed with this
+driver. Good luck!
+
+
+
Siarzuk Zharski
+
http://www.zharik.host.sk/
+
\ No newline at end of file
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/install.sh b/src/add-ons/kernel/drivers/video/usb_vision/install.sh
new file mode 100644
index 0000000000..6bb874e9c0
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/install.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+DRIVER_TITLE="USBVision"
+DRIVER_NAME=usbvision
+
+answer=`alert "Do you really want to install the $DRIVER_TITLE driver?" "No" "Yes"`
+if [ $answer == "No" ]; then
+ exit
+fi
+
+/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/bin/
+/boot/beos/bin/install -d ~/config/settings/kernel/drivers/
+/boot/beos/bin/install -d ~/config/add-ons/kernel/drivers/dev/video/
+/boot/beos/bin/install `dirname $0`/$DRIVER_NAME ~/config/add-ons/kernel/drivers/bin/
+/boot/beos/bin/cp `dirname $0`/$DRIVER_NAME.settings.sample ~/config/settings/kernel/drivers/$DRIVER_NAME
+
+mimeset ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME
+mimeset ~/config/settings/kernel/drivers/$DRIVER_NAME
+
+ln -sf ../../bin/$DRIVER_NAME ~/config/add-ons/kernel/drivers/dev/video/$DRIVER_NAME
+
+rescan $DRIVER_NAME
+
+alert "The $DRIVER_TITLE driver has been installed in your system."
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/tracing.c b/src/add-ons/kernel/drivers/video/usb_vision/tracing.c
new file mode 100644
index 0000000000..e9cbd19d4f
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/tracing.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+
+#include
+//#include
+#include //sprintf
+#include //posix file i/o - create, write, close
+#include
+
+#include "usbvision.h"
+
+#if DEBUG
+bool b_log = true;
+#else
+bool b_log = false;
+#endif
+bool b_log_file = false;
+bool b_log_append = false;
+bool b_log_funcalls = false;
+bool b_log_funcret = false;
+bool b_log_funcres = false;
+
+bool b_log_settings_loaded = false;
+
+static const char *private_log_path="/boot/home/"DRIVER_NAME".log";
+static sem_id loglock;
+
+void load_setting(){
+ if(!b_log_settings_loaded){
+ void *settingshandle;
+ settingshandle = load_driver_settings(DRIVER_NAME);
+#if !DEBUG
+ b_log = get_driver_boolean_parameter(settingshandle, "debug_output", b_log, true);
+#endif
+ b_log_file = get_driver_boolean_parameter(settingshandle, "debug_output_in_file", b_log_file, true);
+ b_log_append = ! get_driver_boolean_parameter(settingshandle, "debug_output_file_rewrite", !b_log_append, true);
+ b_log_funcalls = get_driver_boolean_parameter(settingshandle, "debug_trace_func_calls", b_log_funcalls, false);
+ b_log_funcret = get_driver_boolean_parameter(settingshandle, "debug_trace_func_returns", b_log_funcret, false);
+ b_log_funcres = get_driver_boolean_parameter(settingshandle, "debug_trace_func_results", b_log_funcres, false);
+ unload_driver_settings(settingshandle);
+ b_log_settings_loaded = true;
+ }
+}
+
+void create_log(){
+ int flags = O_WRONLY | O_CREAT | ((!b_log_append) ? O_TRUNC : 0);
+ if(!b_log_file)
+ return;
+ close(open(private_log_path, flags, 0666));
+ loglock = create_sem(1, DRIVER_NAME"-logging");
+}
+
+void usbvision_trace(bool b_force, char *fmt, ...){
+ if(!(b_force || b_log))
+ return;
+ {
+ va_list arg_list;
+ static char *prefix = "\33[32m"DRIVER_NAME":\33[0m";
+ static char buf[1024];
+ char *buf_ptr = buf;
+ if(!b_log_file){
+ strcpy(buf, prefix);
+ buf_ptr += strlen(prefix);
+ }
+
+/* {
+ bigtime_t time = system_time();
+ uint32 msec = time / 1000;
+ uint32 sec = msec / 1000;
+ sprintf(buf_ptr, "%02d.%02d.%03d:", sec / 60, sec % 60, msec % 1000);
+ buf_ptr += strlen(buf_ptr);
+ }
+*/
+ va_start(arg_list, fmt);
+ vsprintf(buf_ptr, fmt, arg_list);
+ va_end(arg_list);
+
+ if(b_log_file){
+ int fd;
+ acquire_sem(loglock);
+ fd = open(private_log_path, O_WRONLY | O_APPEND);
+ write(fd, buf, strlen(buf));
+ close(fd);
+ release_sem(loglock);
+ }
+ else
+ dprintf(buf);
+ }
+}
+
+void trace_reginfo(xet_nt100x_reg *ri)
+{
+ int i;
+ TRACE("struct set_nt100x_reg\n"
+ " reg:%02x\n"
+ " data_length:%d\n",
+ ri->reg, ri->data_length);
+ for(i = 0; i < ri->data_length; i++)
+ TRACE("%02x ", ri->data[i]);
+ TRACE("\n");
+}
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/tracing.h b/src/add-ons/kernel/drivers/video/usb_vision/tracing.h
new file mode 100644
index 0000000000..08908e64e5
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/tracing.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USBVISION_TRACING_H_
+ #define _USBVISION_TRACING_H_
+
+void load_setting();
+void create_log();
+void usbvision_trace(bool b_force, char *fmt, ...);
+
+#define TRACE_ALWAYS(x...) usbvision_trace(true, x);
+#define TRACE(x...) usbvision_trace(false, x);
+
+extern bool b_log_funcalls;
+#define TRACE_FUNCALLS(x...)\
+ { if(b_log_funcalls) usbvision_trace(false, x);}
+
+extern bool b_log_funcret;
+#define TRACE_FUNCRET(x...)\
+ { if(b_log_funcret) usbvision_trace(false, x);}
+
+extern bool b_log_funcres;
+#define TRACE_FUNCRES(func, param)\
+ { if(b_log_funcres) func(param);}
+
+void trace_reginfo(xet_nt100x_reg *reginfo);
+
+#endif /*_USBVISION_TRACING_H_*/
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh b/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh
new file mode 100644
index 0000000000..6ccbaa68a9
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/uninstall.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+DRIVER_TITLE="USBVision"
+DRIVER_NAME=usbvision
+
+answer=`alert "Do you really want to uninstall the $DRIVER_TITLE driver?" "No" "Yes"`
+if [ $answer == "No" ]; then
+ exit
+fi
+
+rm ~/config/add-ons/kernel/drivers/bin/$DRIVER_NAME
+rm ~/config/settings/kernel/drivers/$DRIVER_NAME
+rm ~/config/add-ons/kernel/drivers/dev/video/$DRIVER_NAME
+
+rescan $DRIVER_NAME
+
+alert "The $DRIVER_TITLE driver has been removed from your system."
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c
new file mode 100644
index 0000000000..620f49cbfd
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include /* strerror */
+#include /* strtol */
+#include /* sprintf */
+
+
+#include "usb_vision.h"
+#include "tracing.h"
+
+#define BASENAME_LEN 0x10 /*must be synchronized with below !!!*/
+static const char *basename = "video/usb_vision/%u";
+
+status_t usb_vision_device_added(const usb_device *dev, void **cookie);
+status_t usb_vision_device_removed(void *cookie);
+
+static usb_notify_hooks notify_hooks = {
+ &usb_vision_device_added,
+ &usb_vision_device_removed
+};
+
+struct usb_module_info *usb;
+usb_vision_device *usb_vision_devices[DEVICES_COUNT];
+char * usb_vision_names[DEVICES_COUNT + 1];
+sem_id usb_vision_lock = -1;
+
+struct usb_support_descriptor supported_devices[] = {
+ {0, 0, 0, 0x0573, 0x4d31},
+};
+
+/* init_hardware - called once the first time the driver is loaded */
+status_t init_hardware (void){
+ TRACE("init_hardware\n"); /*special case - no file-logging activated now*/
+ return B_OK;
+}
+
+/* init_driver - optional function - called every time the driver is loaded. */
+status_t init_driver (void){
+ int i;
+ status_t status = B_OK;
+ load_setting();
+ create_log();
+
+ TRACE_FUNCALLS("init_driver\n");
+
+ if((status = get_module(B_USB_MODULE_NAME, (module_info **)&usb)) == B_OK){
+ if(usb){
+ for(i = 0; i < DEVICES_COUNT; i++)
+ usb_vision_devices[i] = 0;
+
+ usb_vision_names[0] = NULL;
+ load_driver_symbols(DRIVER_NAME);
+
+ (*usb->register_driver)(DRIVER_NAME, supported_devices, SIZEOF(supported_devices), DRIVER_NAME);
+ (*usb->install_notify)(DRIVER_NAME, ¬ify_hooks);
+
+ usb_vision_lock = create_sem(1, DRIVER_NAME"_devices_table_lock");
+ }else{
+ status = B_ERROR;
+ TRACE_ALWAYS("init_driver failed: usb:%08x", usb);
+ }
+ }else
+ TRACE_ALWAYS("init_driver failed:%lx cannot get a module %s", status, B_USB_MODULE_NAME);
+
+ TRACE_FUNCRET("init_driver returns:%08x\n", status);
+ return status;
+}
+
+
+/* uninit_driver - optional function - called every time the driver is unloaded */
+void uninit_driver (void){
+ int i;
+ TRACE_FUNCALLS("uninit_driver\n");
+
+ (*usb->uninstall_notify)(DRIVER_NAME);
+ acquire_sem(usb_vision_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++)
+ if(usb_vision_devices[i]){
+ free(usb_vision_devices[i]);
+ usb_vision_devices[i] = 0;
+ }
+
+ release_sem_etc(usb_vision_lock, 1, B_DO_NOT_RESCHEDULE);
+ delete_sem(usb_vision_lock);
+
+ for(i = 0; usb_vision_names[i]; i++)
+ free(usb_vision_names[i]);
+
+ put_module(B_USB_MODULE_NAME);
+}
+
+
+/* usb_vision_open - handle open() calls */
+
+static status_t usb_vision_open (const char *name, uint32 flags, void** cookie)
+{
+ int i;
+ status_t status = ENODEV;
+ TRACE_FUNCALLS("usb_vision_open:%s flags:%d cookie:%08x\n", name, flags, cookie);
+
+ for(i = 0; i < DEVICES_COUNT; i++)
+ TRACE("%08x\n", usb_vision_devices[i]);
+
+ *cookie = NULL;
+ i = strtol(name + BASENAME_LEN, NULL, 10);
+ if(i >= 0 && i < DEVICES_COUNT){
+ acquire_sem(usb_vision_lock);
+ if(usb_vision_devices[i]){
+ if(atomic_add(&usb_vision_devices[i]->open_count, 1) == 0){
+ *cookie = usb_vision_devices[i];
+ TRACE("cookie in open:%08x\n", *cookie);
+ status = B_OK;
+ }else{
+ atomic_add(&usb_vision_devices[i]->open_count, -1);
+ status = B_BUSY;
+ }
+ }
+ release_sem(usb_vision_lock);
+ }
+
+ TRACE_FUNCRET("usb_vision_open returns:%08x\n", status);
+ return status;
+}
+
+/* usb_vision_read - handle read() calls */
+
+static status_t usb_vision_read (void* cookie, off_t position, void *buf, size_t* num_bytes)
+{
+ *num_bytes = 0; /* tell caller nothing was read */
+ return B_IO_ERROR;
+}
+
+
+/* usb_vision_write - handle write() calls */
+
+static status_t usb_vision_write (void* cookie, off_t position, const void* buffer, size_t* num_bytes)
+{
+ *num_bytes = 0; /* tell caller nothing was written */
+ return B_IO_ERROR;
+}
+
+static status_t xet_nt_register(bool is_read, usb_vision_device *uvd, xet_nt100x_reg *ri)
+{
+ status_t status = B_ERROR;
+ uint8 req_type = USB_REQTYPE_VENDOR | (is_read ? USB_REQTYPE_DEVICE_IN : USB_REQTYPE_DEVICE_OUT);
+
+ TRACE_FUNCALLS("set_nt_register:%08x, %08x\n", uvd, ri);
+ TRACE_FUNCRES(trace_reginfo, ri);
+
+ //(*usb->send_request)(uvd->dev, req_type,
+ // )
+
+ TRACE_FUNCRET("set_nt_register returns:%08x\n", status);
+ return status;
+}
+
+/* usb_vision_control - handle ioctl calls */
+static status_t usb_vision_control (void* cookie, uint32 op, void* arg, size_t len)
+{
+ status_t status = B_BAD_VALUE;
+ TRACE_FUNCALLS("usb_vision_control:%08x, %d, %08x, %d\n", cookie, op, arg, len);
+ switch(op){
+ case NT_IOCTL_READ_REGISTER:
+ status = xet_nt_register(true, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
+ break;
+ case NT_IOCTL_WRITE_REGISTER:
+ status = xet_nt_register(false, (usb_vision_device *)cookie, (xet_nt100x_reg *) arg);
+ break;
+ default:
+ break;
+ }
+ TRACE_FUNCRET("usb_vision_control returns:%08x\n", status);
+ return status;
+}
+
+/* usb_vision_close - handle close() calls */
+static status_t usb_vision_close (void* cookie)
+{
+ status_t status = B_OK;//ENODEV;
+ TRACE_FUNCALLS("usb_vision_close:%08x\n", cookie);
+
+ TRACE_FUNCRET("usb_vision_close returns:%08x\n", status);
+ return status;
+}
+
+
+/* usb_vision_free - called after the last device is closed, and after all i/o is complete. */
+static status_t usb_vision_free (void* cookie)
+{
+ status_t status = B_OK;
+ TRACE_FUNCALLS("usb_vision_free:%08x\n", cookie);
+
+ if(cookie){
+ usb_vision_device *uvd = (usb_vision_device *)cookie;
+ atomic_add(&uvd->open_count, -1);
+ }
+
+ TRACE_FUNCRET("usb_vision_free returns:%08x\n", status);
+ return status;
+}
+
+/* function pointers for the device hooks entry points */
+device_hooks usb_vision_hooks = {
+ usb_vision_open, /* -> open entry point */
+ usb_vision_close, /* -> close entry point */
+ usb_vision_free, /* -> free cookie */
+ usb_vision_control, /* -> control entry point */
+ usb_vision_read, /* -> read entry point */
+ usb_vision_write /* -> write entry point */
+};
+
+/* publish_devices - return a null-terminated array of devices
+ supported by this driver. */
+
+const char** publish_devices(){
+ int i, j;
+ TRACE_FUNCALLS("publish_devices\n");
+
+ for(i=0; usb_vision_names[i]; i++)
+ free(usb_vision_names[i]);
+
+ acquire_sem(usb_vision_lock);
+ for(i=0, j=0; i < DEVICES_COUNT; i++){
+ if(usb_vision_devices[i]){
+ usb_vision_names[j] = malloc(strlen(basename + 2));
+ if(usb_vision_names[j]){
+ sprintf(usb_vision_names[j], basename, i);
+ j++;
+ }
+ else
+ TRACE_ALWAYS("publish_devices - NO MEMORY\n");
+ }
+ }
+ usb_vision_names[j] = NULL;
+ release_sem(usb_vision_lock);
+
+ return (const char **)&usb_vision_names[0];
+}
+
+/* find_device - return ptr to device hooks structure for a
+ given device name */
+device_hooks* find_device(const char* name){
+ TRACE_FUNCALLS("find_device(%s)\n", name);
+ return &usb_vision_hooks;
+}
+
+status_t 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){
+// char name[32];
+ status_t status = ENODEV;
+// size_t buf_len;
+ int i = 0;
+
+ TRACE_FUNCALLS("create_add_device(%08x, %08x, %08x, %08x)\n", uvd, uci, control_epi, data_epi);
+
+ acquire_sem(usb_vision_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++){
+ if(usb_vision_devices[i] != NULL)
+ continue;
+
+ usb_vision_devices[i] = uvd;
+ /*
+ usd->active = 1;
+ usd->open = 0;
+
+ sprintf(name, "usb_vision:%d:done_read", i );
+ usd->done_read = create_sem(0, name);
+
+ sprintf(name, "usb_vision:%d:done_write", i);
+ usd->done_write = create_sem(0, name);
+
+ usd->tty = NULL;
+
+ buf_len = usd->read_buffer_size + usd->write_buffer_size + usd->interrupt_buffer_size;
+
+ usd->buffers_area = create_area("usb_serial:buffers_area", (void *)&usd->read_buffer, B_ANY_KERNEL_ADDRESS,
+ ROUNDUP(buf_len, B_PAGE_SIZE),
+ B_CONTIGUOUS, B_READ_AREA|B_WRITE_AREA);
+
+ usd->write_buffer = usd->read_buffer + usd->read_buffer_size;
+ usd->interrupt_buffer = usd->write_buffer + usd->write_buffer_size;
+*/
+ (*usb->set_configuration)(uvd->dev, uci);
+
+ uvd->control_pipe = control_epi->handle;
+ uvd->data_pipe = data_epi->handle;
+
+ status = B_OK;
+ break;
+ }
+ release_sem(usb_vision_lock);
+
+ TRACE_FUNCRET("add_device returns:%08x\n", status);
+ return status;
+}
+
+status_t add_device(usb_vision_device *uvd, const usb_configuration_info *uci){
+ usb_endpoint_info *control_epi = NULL;
+ usb_endpoint_info *data_epi = NULL;
+ status_t status = ENODEV;
+ int i = 0;
+ usb_interface_info *uii = uci->interface[0].active;
+ TRACE_FUNCALLS("> add_device(%08x, %08x)\n", uvd, uci);
+
+ for(i=0; i < uii->endpoint_count; i++){
+ if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_ISOCHRONOUS){
+ if((uii->endpoint[i].descr->endpoint_address & USB_EP_ADDR_DIR_IN) == USB_EP_ADDR_DIR_IN){
+ data_epi = &uii->endpoint[i];
+ TRACE("iso_ep:%d\n", i);
+ }
+ }
+ if(uii->endpoint[i].descr->attributes == USB_EP_ATTR_CONTROL){
+ control_epi = &uii->endpoint[i];
+ TRACE("cont_ep:%d\n", i);
+ }
+ if(control_epi && data_epi)
+ break;
+ }
+
+ if(control_epi && data_epi){
+ status = create_add_device(uvd, uci, control_epi, data_epi);
+ }
+
+ TRACE_FUNCRET("< create_add_device returns:%08x\n", status);
+ return status;
+}
+
+status_t usb_vision_device_added(const usb_device *dev, void **cookie){
+ int dev_idx;
+ status_t status = B_OK;
+ const usb_device_descriptor *udd;
+ usb_vision_device *uvd = 0;
+ TRACE_FUNCALLS("usb_vision_device_added:%08x cookie:%08x\n", dev, cookie);
+
+ udd = (*usb->get_device_descriptor)(dev);
+ TRACE_ALWAYS("Probing device: %08x/%08x\n", udd->vendor_id, udd->product_id);
+
+ *cookie = 0;
+ for(dev_idx = 0; dev_idx < SIZEOF(supported_devices); dev_idx++)
+ if(supported_devices[dev_idx].vendor == udd->vendor_id
+ && supported_devices[dev_idx].product == udd->product_id){
+ const usb_configuration_info *uci;
+ int cfg_idx;
+ for(cfg_idx = 0; (uci = (*usb->get_nth_configuration)(dev, cfg_idx)) != NULL; cfg_idx++){
+ uvd = malloc(sizeof(usb_vision_device));
+ if(uvd){
+ memset(uvd, 0, sizeof(usb_vision_device));
+ uvd->dev = dev;
+ if((status = add_device(uvd, uci)) == B_OK){
+ *cookie = dev;
+ TRACE_ALWAYS("(%04x/%04x) added \n", supported_devices[dev_idx].vendor,
+ supported_devices[dev_idx].product);
+ break;
+ }else
+ free(uvd);
+ }else
+ status = B_NO_MEMORY;
+ }
+ break;
+ }
+
+ TRACE_FUNCRET("usb_vision_device_added returns:%08x\n", status);
+ return status;
+}
+
+status_t usb_vision_device_removed(void *cookie){
+ int i;
+ status_t status = B_OK;
+ struct usb_device *ud = (struct usb_device *) cookie;
+ TRACE_FUNCALLS("usb_vision_device_removed:%08x\n", cookie);
+
+ acquire_sem(usb_vision_lock);
+
+ for(i = 0; i < DEVICES_COUNT; i++ ){
+ usb_vision_device *uvd = usb_vision_devices[i];
+ if(uvd){
+ if(ud == uvd->dev){
+ free(uvd);
+ usb_vision_devices[i] = 0;
+ }
+ }
+ }
+
+ release_sem(usb_vision_lock);
+
+ TRACE_FUNCRET("usb_vision_device_removed returns:%08x\n", status);
+ return status;
+}
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h
new file mode 100644
index 0000000000..cfbd73517e
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2003 by Siarzhuk Zharski
+ * Distributed under the terms of the MIT License.
+ *
+ */
+
+#ifndef _USBVISION_DRIVER_H_
+ #define _USBVISION_DRIVER_H_
+
+#define DRIVER_NAME "usb_vision"
+
+#define DEVICES_COUNT 0x1f
+
+#include "nt100x.h"
+#include "tracing.h"
+
+#define SIZEOF(array) (sizeof(array)/sizeof(array[0]))
+
+/* "forgotten" attributes etc ...*/
+#define USB_EP_ADDR_DIR_IN 0x80
+#define USB_EP_ADDR_DIR_OUT 0x00
+
+#define USB_EP_ATTR_CONTROL 0x00
+#define USB_EP_ATTR_ISOCHRONOUS 0x01
+#define USB_EP_ATTR_BULK 0x02
+#define USB_EP_ATTR_INTERRUPT 0x03
+
+
+typedef struct{
+ uint32 open_count;
+ const usb_device *dev;
+ usb_pipe *control_pipe;
+ usb_pipe *data_pipe;
+} usb_vision_device;
+
+#endif//_USB_SERIAL_DRIVER_H_
diff --git a/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample
new file mode 100644
index 0000000000..27a25a61c2
--- /dev/null
+++ b/src/add-ons/kernel/drivers/video/usb_vision/usb_vision.settings.sample
@@ -0,0 +1,31 @@
+#
+# The sample USBVision driver settings file
+#
+# Rename it to usbvision and put into
+# /boot/home/config/settings/kernel/drivers/
+# After restarting your system the new settings will works.
+
+# Debug output - this is a possibility to view some kind of development related
+# information - error and warning messages etc.
+
+# debug_output - activates debug output. The debug builds has debug output
+# activated by default and this key has no effect on it. The release builds requires
+# to activate this if you want to see debug messages in syslog or in private log file.
+#
+# debug_output true
+
+# debug_output_in_file - activates writing of debug messages into private log file.
+# The name of this file is /boot/home/usbvision.log. If this key is set to true - no messages
+# will be written into syslog.
+#
+# debug_output_in_file true
+
+# debug_output_file_rewrite - activates rewriting of private log file on
+# calling driver_init() syscall. By default this set in false.
+#
+# debug_output_file_rewrite false
+
+# debug_trace_func_calls - the information about driver functions calls
+# will be traced. Would you like to see internals? Then activate this.
+#
+# debug_trace_func_calls true
diff --git a/src/add-ons/media/media-add-ons/Jamfile b/src/add-ons/media/media-add-ons/Jamfile
index 73edbe465d..8949fd2788 100644
--- a/src/add-ons/media/media-add-ons/Jamfile
+++ b/src/add-ons/media/media-add-ons/Jamfile
@@ -8,5 +8,6 @@ SubInclude HAIKU_TOP src add-ons media media-add-ons mixer ;
SubInclude HAIKU_TOP src add-ons media media-add-ons multi_audio ;
SubInclude HAIKU_TOP src add-ons media media-add-ons radeon ;
SubInclude HAIKU_TOP src add-ons media media-add-ons tone_producer_demo ;
+SubInclude HAIKU_TOP src add-ons media media-add-ons usb_vision ;
SubInclude HAIKU_TOP src add-ons media media-add-ons video_producer_demo ;
diff --git a/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp b/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp
new file mode 100644
index 0000000000..8280622cee
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/AddOn.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ * Skeletal part of this code was inherired from original BeOS sample code,
+ * that is distributed under the terms of the Be Sample Code License.
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include "AddOn.h"
+#include "Producer.h"
+
+#include "nt100x.h"
+
+MediaAddOn::MediaAddOn(image_id imid)
+ : BMediaAddOn(imid)
+{
+ /* Customize these parameters to match those of your node */
+ fFlavorInfo.name = "USB Vision";
+ fFlavorInfo.info = "USB Vision";
+ fFlavorInfo.kinds = B_BUFFER_PRODUCER | B_CONTROLLABLE | B_PHYSICAL_INPUT;
+ fFlavorInfo.flavor_flags = 0;
+ fFlavorInfo.internal_id = 0;
+ fFlavorInfo.possible_count = 1;
+ fFlavorInfo.in_format_count = 0;
+ fFlavorInfo.in_format_flags = 0;
+ fFlavorInfo.in_formats = NULL;
+ fFlavorInfo.out_format_count = 1;
+ fFlavorInfo.out_format_flags = 0;
+ fMediaFormat.type = B_MEDIA_RAW_VIDEO;
+ fMediaFormat.u.raw_video = media_raw_video_format::wildcard;
+ fMediaFormat.u.raw_video.interlace = 1;
+ fMediaFormat.u.raw_video.display.format = B_RGB32;
+ fFlavorInfo.out_formats = &fMediaFormat;
+
+ fInitStatus = B_NO_INIT;
+ fDriverFD = -1;
+ if(USBVisionInit()){
+ fInitStatus = B_OK;
+ }
+}
+
+MediaAddOn::~MediaAddOn()
+{
+ if(fInitStatus == B_OK){
+ USBVisionUninit();
+ }
+}
+
+
+status_t
+MediaAddOn::InitCheck(const char **out_failure_text)
+{
+ if (fInitStatus < B_OK) {
+ *out_failure_text = "Unknown error";
+ return fInitStatus;
+ }
+
+ return B_OK;
+}
+
+int32
+MediaAddOn::CountFlavors()
+{
+ if (fInitStatus < B_OK)
+ return fInitStatus;
+
+ /* This addon only supports a single flavor, as defined in the
+ * constructor */
+ return 1;
+}
+
+/*
+ * The pointer to the flavor received only needs to be valid between
+ * successive calls to BMediaAddOn::GetFlavorAt().
+ */
+status_t
+MediaAddOn::GetFlavorAt(int32 n, const flavor_info **out_info)
+{
+ if (fInitStatus < B_OK)
+ return fInitStatus;
+
+ if (n != 0)
+ return B_BAD_INDEX;
+
+ /* Return the flavor defined in the constructor */
+ *out_info = &fFlavorInfo;
+ return B_OK;
+}
+
+BMediaNode *
+MediaAddOn::InstantiateNodeFor(
+ const flavor_info *info, BMessage *config, status_t *out_error)
+{
+ VideoProducer *node;
+
+ if (fInitStatus < B_OK)
+ return NULL;
+
+ if (info->internal_id != fFlavorInfo.internal_id)
+ return NULL;
+
+ /* At most one instance of the node should be instantiated at any given
+ * time. The locking for this restriction may be found in the VideoProducer
+ * class. */
+ node = new VideoProducer(this, fFlavorInfo.name, fFlavorInfo.internal_id);
+ if (node && (node->InitCheck() < B_OK)) {
+ delete node;
+ node = NULL;
+ }
+
+ return node;
+}
+
+BMediaAddOn *
+make_media_addon(image_id imid)
+{
+ return new MediaAddOn(imid);
+}
+
+bool MediaAddOn::USBVisionInit()
+{
+ //TODO - support for multiple devices !!!
+ fDriverFD = open("/dev/video/usb_vision/0", O_RDWR);
+ if(fDriverFD < 0)
+ fInitStatus = ENODEV;
+ return (fDriverFD >= 0);
+}
+
+void MediaAddOn::USBVisionUninit()
+{ //TODO - correct work on detach device from usb port ...
+ close(fDriverFD);
+}
+
+status_t MediaAddOn::USBVisionWriteRegister(uint8 reg, uint8 *data, uint8 len /*= sizeof(uint8)*/)
+{
+ status_t status = ENODEV;
+ if(fDriverFD >= 0){
+ xet_nt100x_reg ri = {reg, len};
+ memcpy(ri.data, data, len);
+ status = ioctl(fDriverFD, NT_IOCTL_WRITE_REGISTER, &ri, sizeof(ri));
+ }
+ return status;
+}
+
+status_t MediaAddOn::USBVisionReadRegister(uint8 reg, uint8 *data, uint8 len /* = sizeof(uint8)*/)
+{
+ status_t status = ENODEV;
+ if(fDriverFD >= 0){
+ xet_nt100x_reg ri = {reg, len};
+ if((status = ioctl(fDriverFD, NT_IOCTL_READ_REGISTER, &ri, sizeof(ri))) == B_OK){
+ memcpy(data, ri.data, ri.data_length);
+ }
+ }
+ return status;
+}
diff --git a/src/add-ons/media/media-add-ons/usb_vision/AddOn.h b/src/add-ons/media/media-add-ons/usb_vision/AddOn.h
new file mode 100644
index 0000000000..d489d7f26e
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/AddOn.h
@@ -0,0 +1,59 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ * Skeletal part of this code was inherired from original BeOS sample code,
+ * that is distributed under the terms of the Be Sample Code License.
+ *
+ */
+
+#ifndef _USBVISION_ADDON_H
+#define _USBVISION_ADDON_H
+
+#include
+
+#define TOUCH(x) ((void)(x))
+
+extern "C" _EXPORT BMediaAddOn *make_media_addon(image_id you);
+
+class MediaAddOn : public BMediaAddOn
+{
+public:
+ MediaAddOn(image_id imid);
+ virtual ~MediaAddOn();
+
+ virtual status_t InitCheck(const char **out_failure_text);
+
+ virtual int32 CountFlavors();
+ virtual status_t GetFlavorAt(int32 n, const flavor_info ** out_info);
+ virtual BMediaNode *InstantiateNodeFor(
+ const flavor_info * info,
+ BMessage * config,
+ status_t * out_error);
+
+ virtual status_t GetConfigurationFor(BMediaNode *node, BMessage *message)
+ { TOUCH(node); TOUCH(message); return B_OK; }
+ virtual status_t SaveConfigInfo(BMediaNode *node, BMessage *message)
+ { TOUCH(node); TOUCH(message); return B_OK; }
+
+ virtual bool WantsAutoStart() { return false; }
+ virtual status_t AutoStart(int in_count, BMediaNode **out_node,
+ int32 *out_internal_id, bool *out_has_more)
+ { TOUCH(in_count); TOUCH(out_node);
+ TOUCH(out_internal_id); TOUCH(out_has_more);
+ return B_ERROR; }
+ bool USBVisionInit();
+ void USBVisionUninit();
+ status_t USBVisionWriteRegister(uint8 reg, uint8 *data, uint8 len = sizeof(uint8));
+ status_t USBVisionReadRegister(uint8 reg, uint8 *data, uint8 len = sizeof(uint8));
+
+private:
+ status_t fInitStatus;
+ flavor_info fFlavorInfo;
+ media_format fMediaFormat;
+ int fDriverFD;
+};
+
+#endif /*_USBVISION_ADDON_H*/
diff --git a/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp b/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp
new file mode 100644
index 0000000000..262cab7178
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/Channels.cpp
@@ -0,0 +1,582 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ */
+
+/* TODO: Look for the following channel lists ...
+Brazil Air
+China Air
+Europe Air
+Europe Cable
+France Air
+France Cable
+Great Britain Air
+Great Britain Cable
+FM Radio
+UKW Radio
+*/
+
+struct Channel{
+ const char *name;
+ float frequency; // in MHz
+};
+
+Channel Channels_US_Air[] = {
+ { "2", 55.25}, { "3", 61.25}, { "4", 67.25}, { "5", 77.25}, { "6", 83.25},
+ { "7", 175.25}, { "8", 181.25}, { "9", 187.25}, { "10", 193.25}, { "11", 199.25},
+ { "12", 205.25}, { "13", 211.25}, { "14", 471.25}, { "15", 477.25}, { "16", 483.25},
+ { "17", 489.25}, { "18", 495.25}, { "19", 501.25}, { "20", 507.25}, { "21", 513.25},
+ { "22", 519.25}, { "23", 525.25}, { "24", 531.25}, { "25", 537.25}, { "26", 543.25},
+ { "27", 549.25}, { "28", 555.25}, { "29", 561.25}, { "30", 567.25}, { "31", 573.25},
+ { "32", 579.25}, { "33", 585.25}, { "34", 591.25}, { "35", 597.25}, { "36", 603.25},
+ { "37", 609.25}, { "38", 615.25}, { "39", 621.25}, { "40", 627.25}, { "41", 633.25},
+ { "42", 639.25}, { "43", 645.25}, { "44", 651.25}, { "45", 657.25}, { "46", 663.25},
+ { "47", 669.25}, { "48", 675.25}, { "49", 681.25}, { "50", 687.25}, { "51", 693.25},
+ { "52", 699.25}, { "53", 705.25}, { "54", 711.25}, { "55", 717.25}, { "56", 723.25},
+ { "57", 729.25}, { "58", 735.25}, { "59", 741.25}, { "60", 747.25}, { "61", 753.25},
+ { "62", 759.25}, { "63", 765.25}, { "64", 771.25}, { "65", 777.25}, { "66", 783.25},
+ { "67", 789.25}, { "68", 795.25}, { "69", 801.25} };
+
+Channel Channels_US_Cable[] = {
+ { "4A", 73.25}, { "2", 55.25}, { "3", 61.25}, { "4", 67.25}, { "5", 77.25},
+ { "6", 83.25}, { "7", 175.25}, { "8", 181.25}, { "9", 187.25}, { "10", 193.25},
+ { "11", 199.25}, { "12", 205.25}, { "13", 211.25}, { "A", 121.25}, { "B", 127.25},
+ { "C", 133.25}, { "D", 139.25}, { "E", 145.25}, { "F", 151.25}, { "G", 157.25},
+ { "H", 163.25}, { "I", 169.25}, { "J", 217.25}, { "K", 223.25}, { "L", 229.25},
+ { "M", 235.25}, { "N", 241.25}, { "O", 247.25}, { "P", 253.25}, { "Q", 259.25},
+ { "R", 265.25}, { "S", 271.25}, { "T", 277.25}, { "U", 283.25}, { "V", 289.25},
+ { "W", 295.25}, { "W+1", 301.25}, { "W+2", 307.25}, { "W+3", 313.25}, { "W+4", 319.25},
+ { "W+5", 325.25}, { "W+6", 331.25}, { "W+7", 337.25}, { "W+8", 343.25}, { "W+9", 349.25},
+ { "W+10", 355.25}, { "W+11", 361.25}, { "W+12", 367.25}, { "W+13", 373.25}, { "W+14", 379.25},
+ { "W+15", 385.25}, { "W+16", 391.25}, { "W+17", 397.25}, { "W+18", 403.25}, { "W+19", 409.25},
+ { "W+20", 415.25}, { "W+21", 421.25}, { "W+22", 427.25}, { "W+23", 433.25}, { "W+24", 439.25},
+ { "W+25", 445.25}, { "W+26", 451.25}, { "W+27", 457.25}, { "W+28", 463.25}, { "65", 469.25},
+ { "66", 475.25}, { "67", 481.25}, { "68", 487.25}, { "69", 493.25}, { "70", 499.25},
+ { "71", 505.25}, { "72", 511.25}, { "73", 517.25}, { "74", 523.25}, { "75", 529.25},
+ { "76", 535.25}, { "77", 541.25}, { "78", 547.25}, { "79", 553.25}, { "80", 559.25},
+ { "81", 565.25}, { "82", 571.25}, { "83", 577.25}, { "84", 583.25}, { "85", 589.25},
+ { "86", 595.25}, { "87", 601.25}, { "88", 607.25}, { "89", 613.25}, { "90", 619.25},
+ { "91", 625.25}, { "92", 631.25}, { "93", 637.25}, { "94", 643.25}, { "A5", 91.25 },
+ { "A4", 97.25 }, { "A3", 103.25}, { "A2", 109.25}, { "A-1", 115.25}, { "100", 649.25},
+ { "101", 655.25}, { "102", 661.25}, { "103", 667.25}, { "104", 673.25}, { "105", 679.25},
+ { "106", 685.25}, { "107", 691.25}, { "108", 697.25}, { "109", 703.25}, { "110", 709.25},
+ { "111", 715.25}, { "112", 721.25}, { "113", 727.25}, { "114", 733.25}, { "115", 739.25},
+ { "116", 745.25}, { "117", 751.25}, { "118", 757.25}, { "119", 763.25}, { "120", 769.25},
+ { "121", 775.25}, { "122", 781.25}, { "123", 787.25}, { "124", 793.25}, { "125", 799.25} };
+
+Channel Channels_US_Cable_HRC[] = {
+ { "2", 54.00}, { "3", 60.00}, { "4", 66.00}, { "5", 76.00},
+ { "6", 82.00}, { "7", 174.00}, { "8", 180.00}, { "9", 186.00}, { "10", 192.00},
+ { "11", 198.00}, { "12", 204.00}, { "13", 210.00}, { "A", 120.00}, { "B", 126.00},
+ { "C", 132.00}, { "D", 138.00}, { "E", 144.00}, { "F", 150.00}, { "G", 156.00},
+ { "H", 162.00}, { "I", 168.00}, { "J", 216.00}, { "K", 222.00}, { "L", 228.00},
+ { "M", 234.00}, { "N", 240.00}, { "O", 246.00}, { "P", 252.00}, { "Q", 258.00},
+ { "R", 264.00}, { "S", 270.00}, { "T", 276.00}, { "U", 282.00}, { "V", 288.00},
+ { "W", 294.00}, { "W+1", 300.00}, { "W+2", 306.00}, { "W+3", 312.00}, { "W+4", 318.00},
+ { "W+5", 324.00}, { "W+6", 330.00}, { "W+7", 336.00}, { "W+8", 342.00}, { "W+9", 348.00},
+ { "W+10", 354.00}, { "W+11", 360.00}, { "W+12", 366.00}, { "W+13", 372.00}, { "W+14", 378.00},
+ { "W+15", 384.00}, { "W+16", 390.00}, { "W+17", 396.00}, { "W+18", 402.00}, { "W+19", 408.00},
+ { "W+20", 414.00}, { "W+21", 420.00}, { "W+22", 426.00}, { "W+23", 432.00}, { "W+24", 438.00},
+ { "W+25", 444.00}, { "W+26", 450.00}, { "W+27", 456.00}, { "W+28", 462.00}, { "65", 468.00},
+ { "66", 474.00}, { "67", 480.00}, { "68", 486.00}, { "69", 492.00}, { "70", 498.00},
+ { "71", 504.00}, { "72", 510.00}, { "73", 516.00}, { "74", 522.00}, { "75", 528.00},
+ { "76", 534.00}, { "77", 540.00}, { "78", 546.00}, { "79", 552.00}, { "80", 558.00},
+ { "81", 564.00}, { "82", 570.00}, { "83", 576.00}, { "84", 582.00}, { "85", 588.00},
+ { "86", 594.00}, { "87", 600.00}, { "88", 606.00}, { "89", 612.00}, { "90", 618.00},
+ { "91", 624.00}, { "92", 630.00}, { "93", 636.00}, { "94", 642.00}, { "A5", 90.00 },
+ { "A4", 96.00 }, { "A3", 102.00}, { "A2", 108.00}, { "A-1", 114.00}, { "100", 648.00},
+ { "101", 654.00}, { "102", 660.00}, { "103", 666.00}, { "104", 672.00}, { "105", 678.00},
+ { "106", 684.00}, { "107", 690.00}, { "108", 696.00}, { "109", 702.00}, { "110", 708.00},
+ { "111", 714.00}, { "112", 720.00}, { "113", 726.00}, { "114", 732.00}, { "115", 738.00},
+ { "116", 744.00}, { "117", 750.00}, { "118", 756.00}, { "119", 762.00}, { "120", 768.00},
+ { "121", 774.00}, { "122", 780.00}, { "123", 786.00}, { "124", 792.00}, { "125", 798.00} };
+
+Channel Japan_Air[]={
+ { "1", 91.25}, { "2", 97.25}, { "3", 103.25}, { "4", 171.25}, { "5", 177.25},
+ { "6", 183.25}, { "7", 189.25}, { "8", 193.25}, { "9", 199.25}, { "10", 205.25},
+ { "11", 211.25}, { "12", 217.25}, { "13", 471.25}, { "14", 477.25}, { "15", 483.25},
+ { "16", 489.25}, { "17", 495.25}, { "18", 501.25}, { "19", 507.25}, { "20", 513.25},
+ { "21", 519.25}, { "22", 525.25}, { "23", 531.25}, { "24", 537.25}, { "25", 543.25},
+ { "26", 549.25}, { "27", 555.25}, { "28", 561.25}, { "29", 567.25}, { "30", 573.25},
+ { "31", 579.25}, { "32", 585.25}, { "33", 591.25}, { "34", 597.25}, { "35", 603.25},
+ { "36", 609.25}, { "37", 615.25}, { "38", 621.25}, { "39", 627.25}, { "40", 633.25},
+ { "41", 639.25}, { "42", 645.25}, { "43", 651.25}, { "44", 657.25}, { "45", 663.25},
+ { "46", 669.25}, { "47", 675.25}, { "48", 681.25}, { "49", 687.25}, { "50", 693.25},
+ { "51", 699.25}, { "52", 705.25}, { "53", 711.25}, { "54", 717.25}, { "55", 723.25},
+ { "56", 729.25}, { "57", 735.25}, { "58", 741.25}, { "59", 747.25}, { "60", 753.25},
+ { "61", 759.25}, { "62", 765.25} };
+
+Channel Japan_Cable[]={
+ { "1", 91.25}, { "2", 97.25}, { "3", 103.25}, { "4", 171.25}, { "5", 177.25},
+ { "6", 183.25}, { "7", 189.25}, { "8", 193.25}, { "9", 199.25}, { "10", 205.25},
+ { "11", 211.25}, { "12", 217.25}, { "C13", 109.25}, { "C14", 115.25}, { "C15", 121.25},
+ { "C16", 127.25}, { "C17", 133.25}, { "C18", 139.25}, { "C19", 145.25}, { "C20", 151.25},
+ { "C21", 157.25}, { "C22", 165.25}, { "C23", 223.25}, { "C24", 229.25}, { "C25", 235.25},
+ { "C26", 241.25}, { "C27", 247.25}, { "C28", 253.25}, { "C29", 259.25}, { "C30", 265.25},
+ { "C31", 271.25}, { "C32", 277.25}, { "C33", 293.25}, { "C34", 289.25}, { "C35", 295.25},
+ { "C36", 301.25}, { "C37", 307.25}, { "C38", 313.25}, { "C39", 319.25}, { "C40", 325.25},
+ { "C41", 331.25}, { "C42", 337.25}, { "C43", 343.25}, { "C44", 349.25}, { "C45", 355.25},
+ { "C46", 361.25}, { "C47", 367.25}, { "C48", 373.25}, { "C49", 379.25}, { "C50", 385.25},
+ { "C51", 391.25}, { "C52", 397.25}, { "C53", 403.25}, { "C54", 409.25}, { "C55", 415.25},
+ { "C56", 421.25}, { "C57", 427.25}, { "C58", 433.25}, { "C59", 439.25}, { "C60", 445.25},
+ { "C61", 451.25}, { "C62", 457.25}, { "C63", 463.25} };
+
+International_Air
+{
+ E2 48.25
+ E3 55.25
+ E4 62.25
+ E5 175.25
+ E6 182.25
+ E7 189.25
+ E8 196.25
+ E9 203.25
+ E10 210.25
+ E11 217.25
+ E12 224.25
+ IA 53.75
+ IB 62.25
+ IC 82.25
+ ID 175.25
+ IE 183.25
+ IF 192.75
+ IG 201.25
+ IH 210.25
+ 21 471.25
+ 22 479.25
+ 23 487.25
+ 24 495.25
+ 25 503.25
+ 26 511.25
+ 27 519.25
+ 28 527.25
+ 29 535.25
+
+ 30 543.25 C30
+ 31 551.25 C31
+ 32 559.25 C32
+ 33 567.25 C33
+ 34 575.25 C34
+ 35 583.25 C35
+ 36 591.25 C36
+ 37 599.25 C37
+ 38 607.25 C38
+ 39 615.25 C39
+ 40 623.25 C40
+ 41 631.25 C41
+ 42 639.25 C42
+ 43 647.25 C43
+ 44 655.25 C44
+ 45 663.25 C45
+ 46 671.25 C46
+ 47 679.25 C47
+ 48 687.25 C48
+ 49 695.25 C49
+ 50 703.25 C50
+ 51 711.25 C51
+ 52 719.25 C52
+ 53 727.25 C53
+ 54 735.25 C54
+ 55 743.25 C55
+ 56 751.25 C56
+ 57 759.25 C57
+ 58 767.25 C58
+ 59 775.25 C59
+ 60 783.25 C60
+ 61 791.25 C61
+ 62 799.25 C62
+ 63 807.25 C63
+ 64 815.25 C64
+ 65 823.25 C65
+ 66 831.25 C66
+ 67 839.25 C67
+ 68 847.25 C68
+ 69 855.25 C69
+ E2A 49.75 C70
+ AS1 57.25 C71
+ AS2 64.25 C72
+ AS3 86.25 C73
+ AS4 95.25 C74
+ AS5 102.25 C75
+ AS5A 138.25
+ AS10 209.25
+ AS11 216.25
+ IH1 217.25
+ IND2 55.25
+ IND3 62.25
+ IND4 175.25
+ IND5 182.25
+ IND6 189.25
+ IND7 196.25
+ IND8 203.25
+ IND9 210.25
+ IND10 217.25
+ IND11 224.25
+
+};
+
+International_Cable
+{
+ Channel Freq
+ E2 48.25
+ E3 55.25
+ E4 62.25
+ S01 69.25
+ S02 76.25
+ S03 83.25
+ S1 105.25
+
+ S2 112.25
+ S3 119.25
+ S4 126.25
+ S5 133.25
+ S6 140.25
+ S7 147.25
+ S8 154.25
+ S9 161.25
+ S10 168.25
+ E5 175.25
+ E6 182.25
+ E7 189.25
+ E8 196.25
+ E9 203.25
+ E10 210.25
+ E11 217.25
+ E12 224.25
+ S11 231.25
+ S12 238.25
+ S13 245.25
+ S14 252.25
+ S15 259.25
+ S16 266.25
+ S17 273.25
+ S18 280.25
+ S19 287.25
+ S20 294.25
+ S21 303.25
+ S22 311.25
+ S23 319.25
+ S24 327.25
+ S25 335.25
+ S26 343.25
+ S27 351.25
+ S28 359.25
+ S29 367.25
+ S30 375.25
+ S31 383.25
+ S32 391.25
+ S33 399.25
+ S34 407.25
+ S35 415.25
+ S36 423.25
+ S37 431.25
+ S38 439.25
+ S39 447.25
+ S40 455.25
+ S41 463.25
+};
+
+Channel UK_Air[] = {
+ { "A", 45.75}, { "B", 53.75}, { "C", 61.75}, { "D", 175.25}, { "E", 183.25},
+ { "F", 191.25}, { "G", 199.25}, { "H", 207.25}, { "J", 215.25}, { "C10", 223.25},
+ { "C11", 231.25}, { "C13", 247.25}, { "B21", 471.25}, { "B22", 479.25}, { "B23", 487.25},
+ { "B24", 495.25}, { "B25", 503.25}, { "B26", 511.25}, { "B27", 519.25}, { "B28", 527.25},
+ { "B29", 535.25}, { "B30", 543.25}, { "B31", 551.25}, { "B32", 559.25}, { "B33", 567.25},
+ { "B34", 575.25}, { "B35", 583.25}, { "B36", 591.25}, { "B37", 599.25}, { "B38", 607.25},
+ { "B39", 615.25}, { "B40", 623.25}, { "B41", 631.25}, { "B42", 639.25}, { "B43", 647.25},
+ { "B44", 655.25}, { "B45", 663.25}, { "B46", 671.25}, { "B47", 679.25}, { "B48", 687.25},
+ { "B49", 695.25}, { "B50", 703.25}, { "B51", 711.25}, { "B52", 719.25}, { "B53", 727.25},
+ { "B54", 735.25}, { "B55", 743.25}, { "B56", 751.25}, { "B57", 759.25}, { "B58", 767.25},
+ { "B59", 775.25}, { "B60", 783.25}, { "B61", 791.25}, { "B62", 799.25}, { "B63", 807.25},
+ { "B64", 815.25}, { "B65", 823.25}, { "B66", 831.25}, { "B67", 839.25}, { "B68", 847.25},
+ { "B69", 855.25}, { "B1", 45.00 }, { "B2", 51.75 }, { "B3", 56.75 }, { "B4", 61.75 },
+ { "B5", 66.75 }, { "B6", 179.75}, { "B7", 184.75}, { "B8", 189.75}, { "B9", 194.75},
+ { "B10", 199.75}, { "B11", 204.75}, { "B12", 209.75}, { "B13", 214.75}, { "B14", 219.75} };
+
+UK_Cable
+{
+ Channel Freq
+ A1 47.25
+ A2 55.25
+
+ A3 63.25
+ A4 71.25
+ A5 79.25
+ A6 87.25
+ A7 95.25
+ A8 103.25
+ A9 111.25
+ A10 119.25
+ A11 127.25
+ A12 135.25
+ A13 143.25
+ A14 151.25
+ A15 159.25
+ A16 167.25
+ A17 175.25
+ A18 183.25
+ A19 191.25
+ A20 199.25
+ A21 207.25
+ A22 215.25
+ A23 223.25
+ A24 231.25
+ A25 239.25
+ A26 247.25
+ A27 255.25
+ A28 263.25
+ A29 271.25
+ A30 279.25
+ A31 287.25
+ A32 295.25
+ E2 48.25
+ E3 55.25
+ E4 62.25
+ S01 69.25
+ S02 76.25
+ S03 83.25
+ S1 105.25
+ S2 112.25
+ S3 119.25
+ S4 126.25
+ S5 133.25
+ S6 140.25
+ S7 147.25
+ S8 154.25
+ S9 161.25
+ S10 168.25
+ E5 175.25
+ E6 182.25
+ E7 189.25
+ E8 196.25
+ E9 203.25
+ E10 210.25
+ E11 217.25
+ E12 224.25
+ S11 231.25
+ S12 238.25
+ S13 245.25
+ S14 252.25
+ S15 259.25
+ S16 266.25
+ S17 273.25
+ S18 280.25
+ S19 287.25
+ S20 294.25
+ S21 303.25
+ S22 311.25
+ S23 319.25
+ S24 327.25
+ S25 335.25
+ S26 343.25
+ S27 351.25
+ S28 359.25
+
+ S29 367.25
+ S30 375.25
+ S31 383.25
+ S32 391.25
+ S33 399.25
+ S34 407.25
+ S35 415.25
+ S36 423.25
+ S37 431.25
+ S38 439.25
+ S39 447.25
+ S40 455.25
+ S41 463.25
+
+};
+
+French_Air
+{
+ Channel Freq
+ FA 47.75
+ L2 49.25
+ L3 54.00
+ FB 55.75
+ L4 57.25
+ FC1 60.50
+ FC 63.75
+ F1 176.00
+ F2 184.00
+ F3 192.00
+ F4 200.00
+ F5 208.00
+ F6 216.00
+ B21 471.25
+ B22 479.25
+ B23 487.25
+ B24 495.25
+ B25 503.25
+ B26 511.25
+ B27 519.25
+ B28 527.25
+ B29 535.25
+ B30 543.25
+ B31 551.25
+ B32 559.25
+ B33 567.25
+ B34 575.25
+ B35 583.25
+ B36 591.25
+ B37 599.25
+ B38 607.25
+ B39 615.25
+ B40 623.25
+ B41 631.25
+ B42 639.25
+ B43 647.25
+ B44 655.25
+ B45 663.25
+ B46 671.25
+ B47 679.25
+ B48 687.25
+ B49 695.25
+ B50 703.25
+ B51 711.25
+ B52 719.25
+
+
+ B53 727.25
+ B54 735.25
+ B55 743.25
+ B56 751.25
+ B57 759.25
+ B58 767.25
+ B59 775.25
+ B60 783.25
+ B61 791.25
+ B62 799.25
+ B63 807.25
+ B64 815.25
+ B65 823.25
+ B66 831.25
+ B67 839.25
+ B68 847.25
+ B69 855.25
+
+};
+
+French_Cable
+{
+ Channel Freq
+ E2 48.25
+ E3 55.25
+ E4 62.25
+ S01 69.25
+ S02 76.25
+ S03 83.25
+ S1 105.25
+ S2 112.25
+ S3 119.25
+ S4 126.25
+ S5 133.25
+ S6 140.25
+ S7 147.25
+ S8 154.25
+ S9 161.25
+ S10 168.25
+ E5 175.25
+ E6 182.25
+ E7 189.25
+ E8 196.25
+ E9 203.25
+ E10 210.25
+ E11 217.25
+ E12 224.25
+ S11 231.25
+ S12 238.25
+ S13 245.25
+ S14 252.25
+ S15 259.25
+ S16 266.25
+ S17 273.25
+ S18 280.25
+ S19 287.25
+ S20 294.25
+ S21 303.25
+ S22 311.25
+ S23 319.25
+ S24 327.25
+ S25 335.25
+ S26 343.25
+ S27 351.25
+ S28 359.25
+ S29 367.25
+ S30 375.25
+ S31 383.25
+ S32 391.25
+ S33 399.25
+ S34 407.25
+ S35 415.25
+ S36 423.25
+
+ S37 431.25
+ S38 439.25
+ S39 447.25
+ S40 455.25
+ S41 463.25
+
+};
+
+Channel Channels_FMRadio[] = {
+/*???*/
+};
+
+Channel Channels_UKW_Radio[] = {
+/*???*/
+};
+
+Channel Channels_xUSSR_Air[] = {
+ {"1", 49.75}, {"2", 59.25}, {"3", 77.25}, {"4", 85.25}, {"5", 93.25},
+ {"6", 175.25}, {"7", 183.25}, {"8", 191.25}, {"9", 199.25}, {"10", 207.25},
+ {"11", 215.25}, {"12", 223.25},
+ {"21", 471.25}, {"22", 479.25}, {"23", 487.25}, {"24", 495.25}, {"25", 503.25},
+ {"26", 511.25}, {"27", 519.25}, {"28", 527.25}, {"29", 535.25}, {"30", 543.25},
+ {"31", 551.25}, {"32", 559.25}, {"33", 567.25}, {"34", 575.25}, {"35", 583.25},
+ {"36", 591.25}, {"37", 599.25}, {"38", 607.25}, {"39", 615.25}, {"40", 623.25},
+ {"41", 631.25}, {"42", 639.25}, {"43", 647.25}, {"44", 655.25}, {"45", 663.25},
+ {"46", 671.25}, {"47", 679.25}, {"48", 687.25}, {"49", 695.25}, {"50", 703.25},
+ {"51", 711.25}, {"52", 719.25}, {"53", 727.25}, {"54", 735.25}, {"55", 743.25},
+ {"56", 751.25}, {"57", 759.25}, {"58", 767.25}, {"59", 775.25}, {"60", 783.25},
+ {"61", 791.25}, {"62", 799.25}, {"63", 807.25}, {"64", 815.25}, {"65", 823.25},
+ {"66", 831.25}, {"67", 839.25}, {"68", 847.25}, {"69", 855.25}};
+
+Channel Channels_xUSSR_Cable[] = {
+ {"70", 111.25}, {"71", 119.25}, {"72", 127.25}, {"73", 135.25}, {"74", 143.25},
+ {"75", 141.25}, {"76", 159.25}, {"77", 167.25}, {"78", 231.25}, {"79", 239.25},
+ {"80", 247.25}, {"81", 255.25}, {"82", 263.25}, {"83", 271.25}, {"84", 279.25},
+ {"85", 287.25}, {"86", 295.25}, {"87", 303.25}, {"88", 311.25}, {"89", 319.25},
+ {"90", 327.25}, {"91", 335.25}, {"92", 343.25}, {"93", 351.25}, {"94", 359.25},
+ {"95", 367.25}, {"96", 375.25}, {"97", 383.25}, {"98", 391.25}, {"99", 399.25},
+ {"100", 407.25}, {"101", 415.25}, {"102", 423.25}, {"103", 431.25}, {"104", 439.25},
+ {"105", 447.25}, {"106", 455.25}, {"107", 463.25} };
+
+Channel Channels_EuropeAir[] = {
+ {"", }, {"", }, {"", }, {"", }, {"", }, {"", },
+};
+
+Channel Channels_EuropeCable[] = {
+ {"", }, {"", }, {"", }, {"", }, {"", }, {"", },
+};
+
+Channel Channels_AustraliaAir[] = {
+ { "0", 46.25}, { "1", 57.25}, { "2", 64.25}, { "3", 86.25}, { "4", 95.25},
+ { "5", 102.25}, { "5A", 138.25}, { "6", 175.25}, { "7", 182.25}, { "8", 189.25},
+ { "9", 196.25}, { "10", 209.25}, { "11", 216.25}, { "28", 527.25}, { "29", 534.25},
+ { "30", 541.25}, { "31", 548.25}, { "32", 555.25}, { "33", 562.25}, { "34", 569.25},
+ { "35", 576.25}, { "39", 604.25}, { "40", 611.25}, { "41", 618.25}, { "42", 625.25},
+ { "43", 632.25}, { "44", 639.25}, { "45", 646.25}, { "46", 653.25}, { "47", 660.25},
+ { "48", 667.25}, { "49", 674.25}, { "50", 681.25}, { "51", 688.25}, { "52", 695.25},
+ { "53", 702.25}, { "54", 709.25}, { "55", 716.25}, { "56", 723.25}, { "57", 730.25},
+ { "58", 737.25}, { "59", 744.25}, { "60", 751.25}, { "61", 758.25}, { "62", 765.25},
+ { "63", 772.25}, { "64", 779.25}, { "65", 786.25}, { "66", 793.25}, { "67", 800.25},
+ { "68", 807.25}, { "69", 814.25} };
+
+Channel Channels_IrelandAir[] = {
+
+};
diff --git a/src/add-ons/media/media-add-ons/usb_vision/Jamfile b/src/add-ons/media/media-add-ons/usb_vision/Jamfile
new file mode 100644
index 0000000000..52088512de
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/Jamfile
@@ -0,0 +1,13 @@
+SubDir HAIKU_TOP src add-ons media media-add-ons usb_vision ;
+
+SetSubDirSupportedPlatformsBeOSCompatible ;
+
+UsePrivateHeaders usb_vision ;
+
+Addon usb_vision.media_addon : media :
+ AddOn.cpp
+ Producer.cpp
+ TunerLocale.cpp
+;
+
+LinkAgainst usb_vision.media_addon : be media $(TARGET_LIBSTDC++) ;
diff --git a/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp b/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp
new file mode 100644
index 0000000000..5582de3f18
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/Producer.cpp
@@ -0,0 +1,1173 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ * Skeletal part of this code was inherired from original BeOS sample code,
+ * that is distributed under the terms of the Be Sample Code License.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define TOUCH(x) ((void)(x))
+
+#define PRINTF(a,b) \
+ do { \
+ if (a < 2) { \
+ printf("VideoProducer::"); \
+ printf b; \
+ } \
+ } while (0)
+
+#include "Producer.h"
+
+#define FIELD_RATE 30.f
+
+const float kUSBBandWidthMin = 0.5f;
+const float kUSBBandWidthMax = 7.5f;
+const float kUSBBandWidthStep = 0.5f;
+
+const float kVScreenOffsetMin = 0.f;
+const float kVScreenOffsetMax = 4.f;
+const float kVScreenOffsetStep = 1.f;
+const float kHScreenOffsetMin = 0.f;
+const float kHScreenOffsetMax = 4.f;
+const float kHScreenOffsetStep = 1.f;
+
+const float kEffectMin = 0.f;
+const float kEffectMax = 31.f;
+const float kEffectStep = 1.f;
+
+const float kBrightnessMin = kEffectMin;
+const float kBrightnessMax = kEffectMax;
+const float kBrightnessStep = kEffectStep;
+
+const float kContrastMin = kEffectMin;
+const float kContrastMax = kEffectMax;
+const float kContrastStep = kEffectStep;
+
+const float kHueMin = kEffectMin;
+const float kHueMax = kEffectMax;
+const float kHueStep = kEffectStep;
+
+const float kSaturationMin = kEffectMin;
+const float kSaturationMax = kEffectMax;
+const float kSaturationStep = kEffectStep;
+
+const uint32 kDefChannel = 0;
+//const VideoInput kDefVideoInput = P_VI_TUNER;
+const uint32 kDefAudioInput = 0;
+const uint32 kDefBrightness = 20;
+const uint32 kDefContrast = 22;
+const uint32 kDefSaturation = 15;
+const uint32 kDefHue = 20;
+const uint32 kDefCaptureSize = 0;
+const uint32 kDefCaptureFormat = 0;
+//const VideoStandard kDefStandard = P_VF_PAL_BDGHI;
+const float kDefBandwidth = 7.0;
+const uint32 kDefLocale = 0;
+const uint32 kDefVertOffset = 1;
+const uint32 kDefHorzOffset = 2;
+
+int32 VideoProducer::fInstances = 0;
+
+VideoProducer::VideoProducer(
+ BMediaAddOn *addon, const char *name, int32 internal_id)
+ : BMediaNode(name),
+ BMediaEventLooper(),
+ BBufferProducer(B_MEDIA_RAW_VIDEO),
+ BControllable()
+{
+ status_t err;
+
+ fInitStatus = B_NO_INIT;
+
+ /* Only allow one instance of the node to exist at any time */
+ if (atomic_add(&fInstances, 1) != 0)
+ return;
+
+ fInternalID = internal_id;
+ fAddOn = addon;
+
+ fBufferGroup = NULL;
+
+ fThread = -1;
+ fFrameSync = -1;
+ fProcessingLatency = 0LL;
+
+ fRunning = false;
+ fConnected = false;
+ fEnabled = false;
+
+ fOutput.destination = media_destination::null;
+
+ AddNodeKind(B_PHYSICAL_INPUT);
+
+ fInitStatus = B_OK;
+
+ //debugger("op-op");
+
+ status_t status = Locale::TunerLocale::LoadLocales(fLocales);
+
+ printf("LoadLocales:%08x\n", status);
+
+ fChannel = kDefChannel;
+ fVideoInput = P_VI_TUNER;
+ fAudioInput = kDefAudioInput;
+ fBrightness = kDefBrightness;
+ fContrast = kDefContrast;
+ fSaturation = kDefSaturation;
+ fHue = kDefHue;
+ fCaptureSize = kDefCaptureSize;
+ fCaptureFormat = kDefCaptureFormat;
+ fStandard = P_VF_PAL_BDGHI;
+ fLocale = kDefLocale;
+ fBandwidth = kDefBandwidth;
+ fVertOffset = kDefVertOffset;
+ fHorzOffset = kDefHorzOffset;
+ fColor = B_HOST_TO_LENDIAN_INT32(0x00ff0000);
+
+ fLastChannelChange =
+ fLastVideoInputChange =
+ fLastAudioInputChange =
+ fLastBrightnessChange =
+ fLastContrastChange =
+ fLastSaturationChange =
+ fLastHueChange =
+ fLastCaptureSizeChange =
+ fLastCaptureFormatChange =
+ fLastStandardChange =
+ fLastLocaleChange =
+ fLastBandwidthChange =
+ fLastVertOffsetChange =
+ fLastHorzOffsetChange =
+ fLastColorChange = system_time();
+
+ return;
+}
+
+VideoProducer::~VideoProducer()
+{
+ if (fInitStatus == B_OK) {
+ /* Clean up after ourselves, in case the application didn't make us
+ * do so. */
+ if (fConnected)
+ Disconnect(fOutput.source, fOutput.destination);
+ if (fRunning)
+ HandleStop();
+ }
+
+ atomic_add(&fInstances, -1);
+
+ Locale::TunerLocale::ReleaseLocales(fLocales);
+}
+
+/* BMediaNode */
+
+port_id
+VideoProducer::ControlPort() const
+{
+ return BMediaNode::ControlPort();
+}
+
+BMediaAddOn *
+VideoProducer::AddOn(int32 *internal_id) const
+{
+ if (internal_id)
+ *internal_id = fInternalID;
+ return fAddOn;
+}
+
+status_t
+VideoProducer::HandleMessage(int32 message, const void *data, size_t size)
+{
+ return B_ERROR;
+}
+
+void
+VideoProducer::Preroll()
+{
+ /* This hook may be called before the node is started to give the hardware
+ * a chance to start. */
+}
+
+void
+VideoProducer::SetTimeSource(BTimeSource *time_source)
+{
+ /* Tell frame generation thread to recalculate delay value */
+ release_sem(fFrameSync);
+}
+
+status_t
+VideoProducer::RequestCompleted(const media_request_info &info)
+{
+ return BMediaNode::RequestCompleted(info);
+}
+
+/* BMediaEventLooper */
+
+void
+VideoProducer::NodeRegistered()
+{
+ if (fInitStatus != B_OK) {
+ ReportError(B_NODE_IN_DISTRESS);
+ return;
+ }
+
+ /* After this call, the BControllable owns the BParameterWeb object and
+ * will delete it for you */
+ SetParameterWeb(CreateParameterWeb());
+
+ fOutput.node = Node();
+ fOutput.source.port = ControlPort();
+ fOutput.source.id = 0;
+ fOutput.destination = media_destination::null;
+ strcpy(fOutput.name, Name());
+
+ /* Tailor these for the output of your device */
+ fOutput.format.type = B_MEDIA_RAW_VIDEO;
+ fOutput.format.u.raw_video = media_raw_video_format::wildcard;
+ fOutput.format.u.raw_video.interlace = 1;
+ fOutput.format.u.raw_video.display.format = B_RGB32;
+
+ /* Start the BMediaEventLooper control loop running */
+ Run();
+}
+
+BParameterWeb *VideoProducer::CreateParameterWeb()
+{
+ /* Set up the parameter web */
+ BParameterWeb *web = new BParameterWeb();
+
+ BParameterGroup *controls = web->MakeGroup("Controls");
+ BParameterGroup *group = controls->MakeGroup("Main Controls");
+ BDiscreteParameter *parameter = group->MakeDiscreteParameter(
+ P_CHANNEL, B_MEDIA_NO_TYPE, "Channel:", B_GENERIC);
+ for(int i = 0; i < fLocales[fLocale]->ChannelsCount(); i ++){
+ parameter->AddItem(i, (fLocales[fLocale]->GetChannel(i)).Name().c_str());
+ }
+
+ parameter = group->MakeDiscreteParameter(
+ P_VIDEO_INPUT, B_MEDIA_NO_TYPE, "Video Input:", B_INPUT_MUX);
+ parameter->AddItem(P_VI_TUNER, "Tuner");
+ parameter->AddItem(P_VI_COMPOSITE, "Composite");
+ parameter->AddItem(P_VI_SVIDEO, "SVideo");
+
+ parameter = group->MakeDiscreteParameter(
+ P_AUDIO_INPUT, B_MEDIA_NO_TYPE, "Audio Input:", B_INPUT_MUX);
+ parameter->AddItem(1, "TODO");
+ parameter->AddItem(2, "TODO");
+ parameter->AddItem(3, "TODO");
+
+ group = controls->MakeGroup("Effect Controls");
+ group->MakeContinuousParameter(
+ P_BRIGHTNESS, B_MEDIA_NO_TYPE, "Brightness", B_LEVEL,
+ "", kBrightnessMin, kBrightnessMax, kBrightnessStep);
+
+ group->MakeContinuousParameter(
+ P_CONTRAST, B_MEDIA_NO_TYPE, "Contrast", B_LEVEL,
+ "", kContrastMin, kContrastMax, kContrastStep);
+
+ group = controls->MakeGroup("Adv. Effect Controls");
+ group->MakeContinuousParameter(
+ P_SATURATION, B_MEDIA_NO_TYPE, "Saturation", B_LEVEL,
+ "", kSaturationMin, kSaturationMax, kSaturationStep);
+
+ group->MakeContinuousParameter(
+ P_HUE, B_MEDIA_NO_TYPE, "Hue", B_LEVEL,
+ "", kHueMin, kHueMax, kHueStep);
+
+ BParameterGroup *options = web->MakeGroup("Options");
+ group = options->MakeGroup("Capture Option");
+ parameter = group->MakeDiscreteParameter(
+ P_CAPTURE_SIZE, B_MEDIA_NO_TYPE, "Capture Size:", B_RESOLUTION);
+ parameter->AddItem(1, "TODO");
+ parameter->AddItem(2, "TODO");
+
+ parameter = group->MakeDiscreteParameter(
+ P_CAPTURE_FORMAT, B_MEDIA_NO_TYPE, "Capture Format:", B_COLOR_SPACE);
+ parameter->AddItem(1, "TODO");
+ parameter->AddItem(2, "TODO");
+
+ BParameterGroup *hardware = web->MakeGroup("Hardware Setup");
+ group = hardware->MakeGroup("Format");
+ parameter = group->MakeDiscreteParameter(
+ P_STANDART, B_MEDIA_NO_TYPE, "Video Format:", B_VIDEO_FORMAT);
+ parameter->AddItem(P_VF_NTSC_M, "NTSC M");
+ parameter->AddItem(P_VF_NTSC_MJ, "NTSC MJ");
+ parameter->AddItem(P_VF_PAL_BDGHI, "PAL BDGHI");
+ parameter->AddItem(P_VF_PAL_M, "PAL M");
+ parameter->AddItem(P_VF_PAL_N, "PAL N");
+ parameter->AddItem(P_VF_SECAM, "SECAM");
+
+ parameter = group->MakeDiscreteParameter(
+ P_LOCALE, B_MEDIA_NO_TYPE, "Tuner Locale:", B_GENERIC);
+ for(int i = 0; i < fLocales.size(); i++)
+ parameter->AddItem(i, fLocales[i]->Name().c_str());
+
+ group = hardware->MakeGroup("Format");
+
+ group->MakeContinuousParameter(
+ P_BANDWIDTH, B_MEDIA_NO_TYPE, "Max.Bandwidth", B_LEVEL,
+ "", kUSBBandWidthMin, kUSBBandWidthMax, kUSBBandWidthStep);
+
+ group = hardware->MakeGroup("Offsets");
+
+ group->MakeContinuousParameter(
+ P_VERT_OFFSET, B_MEDIA_NO_TYPE, "Vertical Offset", B_LEVEL,
+ "", kVScreenOffsetMin, kVScreenOffsetMax, kVScreenOffsetStep);
+
+ group->MakeContinuousParameter(
+ P_HORZ_OFFSET, B_MEDIA_NO_TYPE, "Horizontal Offset", B_LEVEL,
+ "", kHScreenOffsetMin, kHScreenOffsetMax, kHScreenOffsetStep);
+
+ BParameterGroup *main = web->MakeGroup(Name());
+ BDiscreteParameter *state = main->MakeDiscreteParameter(
+ P_COLOR, B_MEDIA_RAW_VIDEO, "Color", "Color");
+ state->AddItem(B_HOST_TO_LENDIAN_INT32(0x00ff0000), "Red");
+ state->AddItem(B_HOST_TO_LENDIAN_INT32(0x0000ff00), "Green");
+ state->AddItem(B_HOST_TO_LENDIAN_INT32(0x000000ff), "Blue");
+
+ return web;
+}
+
+void
+VideoProducer::Start(bigtime_t performance_time)
+{
+ BMediaEventLooper::Start(performance_time);
+}
+
+void
+VideoProducer::Stop(bigtime_t performance_time, bool immediate)
+{
+ BMediaEventLooper::Stop(performance_time, immediate);
+}
+
+void
+VideoProducer::Seek(bigtime_t media_time, bigtime_t performance_time)
+{
+ BMediaEventLooper::Seek(media_time, performance_time);
+}
+
+void
+VideoProducer::TimeWarp(bigtime_t at_real_time, bigtime_t to_performance_time)
+{
+ BMediaEventLooper::TimeWarp(at_real_time, to_performance_time);
+}
+
+status_t
+VideoProducer::AddTimer(bigtime_t at_performance_time, int32 cookie)
+{
+ return BMediaEventLooper::AddTimer(at_performance_time, cookie);
+}
+
+void
+VideoProducer::SetRunMode(run_mode mode)
+{
+ BMediaEventLooper::SetRunMode(mode);
+}
+
+void
+VideoProducer::HandleEvent(const media_timed_event *event,
+ bigtime_t lateness, bool realTimeEvent)
+{
+ TOUCH(lateness); TOUCH(realTimeEvent);
+
+ switch(event->type)
+ {
+ case BTimedEventQueue::B_START:
+ HandleStart(event->event_time);
+ break;
+ case BTimedEventQueue::B_STOP:
+ HandleStop();
+ break;
+ case BTimedEventQueue::B_WARP:
+ HandleTimeWarp(event->bigdata);
+ break;
+ case BTimedEventQueue::B_SEEK:
+ HandleSeek(event->bigdata);
+ break;
+ case BTimedEventQueue::B_PARAMETER:
+ HandleParameter(event->data);
+ break;
+ case BTimedEventQueue::B_HANDLE_BUFFER:
+ case BTimedEventQueue::B_DATA_STATUS:
+ default:
+ PRINTF(-1, ("HandleEvent: Unhandled event -- %lx\n", event->type));
+ break;
+ }
+}
+
+void
+VideoProducer::CleanUpEvent(const media_timed_event *event)
+{
+ BMediaEventLooper::CleanUpEvent(event);
+}
+
+bigtime_t
+VideoProducer::OfflineTime()
+{
+ return BMediaEventLooper::OfflineTime();
+}
+
+void
+VideoProducer::ControlLoop()
+{
+ BMediaEventLooper::ControlLoop();
+}
+
+status_t
+VideoProducer::DeleteHook(BMediaNode * node)
+{
+ return BMediaEventLooper::DeleteHook(node);
+}
+
+/* BBufferProducer */
+
+status_t
+VideoProducer::FormatSuggestionRequested(
+ media_type type, int32 quality, media_format *format)
+{
+ if (type != B_MEDIA_ENCODED_VIDEO)
+ return B_MEDIA_BAD_FORMAT;
+
+ TOUCH(quality);
+
+ *format = fOutput.format;
+ return B_OK;
+}
+
+status_t
+VideoProducer::FormatProposal(const media_source &output, media_format *format)
+{
+ status_t err;
+
+ if (!format)
+ return B_BAD_VALUE;
+
+ if (output != fOutput.source)
+ return B_MEDIA_BAD_SOURCE;
+
+ err = format_is_compatible(*format, fOutput.format) ?
+ B_OK : B_MEDIA_BAD_FORMAT;
+ *format = fOutput.format;
+ return err;
+
+}
+
+status_t
+VideoProducer::FormatChangeRequested(const media_source &source,
+ const media_destination &destination, media_format *io_format,
+ int32 *_deprecated_)
+{
+ TOUCH(destination); TOUCH(io_format); TOUCH(_deprecated_);
+ if (source != fOutput.source)
+ return B_MEDIA_BAD_SOURCE;
+
+ return B_ERROR;
+}
+
+status_t
+VideoProducer::GetNextOutput(int32 *cookie, media_output *out_output)
+{
+ if (!out_output)
+ return B_BAD_VALUE;
+
+ if ((*cookie) != 0)
+ return B_BAD_INDEX;
+
+ *out_output = fOutput;
+ (*cookie)++;
+ return B_OK;
+}
+
+status_t
+VideoProducer::DisposeOutputCookie(int32 cookie)
+{
+ TOUCH(cookie);
+
+ return B_OK;
+}
+
+status_t
+VideoProducer::SetBufferGroup(const media_source &for_source,
+ BBufferGroup *group)
+{
+ TOUCH(for_source); TOUCH(group);
+
+ return B_ERROR;
+}
+
+status_t
+VideoProducer::VideoClippingChanged(const media_source &for_source,
+ int16 num_shorts, int16 *clip_data,
+ const media_video_display_info &display, int32 *_deprecated_)
+{
+ TOUCH(for_source); TOUCH(num_shorts); TOUCH(clip_data);
+ TOUCH(display); TOUCH(_deprecated_);
+
+ return B_ERROR;
+}
+
+status_t
+VideoProducer::GetLatency(bigtime_t *out_latency)
+{
+ *out_latency = EventLatency() + SchedulingLatency();
+ return B_OK;
+}
+
+status_t
+VideoProducer::PrepareToConnect(const media_source &source,
+ const media_destination &destination, media_format *format,
+ media_source *out_source, char *out_name)
+{
+ status_t err;
+
+ PRINTF(1, ("PrepareToConnect() %ldx%ld\n", \
+ format->u.raw_video.display.line_width, \
+ format->u.raw_video.display.line_count));
+
+ if (fConnected) {
+ PRINTF(0, ("PrepareToConnect: Already connected\n"));
+ return EALREADY;
+ }
+
+ if (source != fOutput.source)
+ return B_MEDIA_BAD_SOURCE;
+
+ if (fOutput.destination != media_destination::null)
+ return B_MEDIA_ALREADY_CONNECTED;
+
+ /* The format parameter comes in with the suggested format, and may be
+ * specialized as desired by the node */
+ if (!format_is_compatible(*format, fOutput.format)) {
+ *format = fOutput.format;
+ return B_MEDIA_BAD_FORMAT;
+ }
+
+ if (format->u.raw_video.display.line_width == 0)
+ format->u.raw_video.display.line_width = 320;
+ if (format->u.raw_video.display.line_count == 0)
+ format->u.raw_video.display.line_count = 240;
+ if (format->u.raw_video.field_rate == 0)
+ format->u.raw_video.field_rate = 29.97f;
+
+ *out_source = fOutput.source;
+ strcpy(out_name, fOutput.name);
+
+ fOutput.destination = destination;
+
+ return B_OK;
+}
+
+void
+VideoProducer::Connect(status_t error, const media_source &source,
+ const media_destination &destination, const media_format &format,
+ char *io_name)
+{
+ PRINTF(1, ("Connect() %ldx%ld\n", \
+ format.u.raw_video.display.line_width, \
+ format.u.raw_video.display.line_count));
+
+ if (fConnected) {
+ PRINTF(0, ("Connect: Already connected\n"));
+ return;
+ }
+
+ if ( (source != fOutput.source) || (error < B_OK) ||
+ !const_cast(&format)->Matches(&fOutput.format)) {
+ PRINTF(1, ("Connect: Connect error\n"));
+ return;
+ }
+
+ fOutput.destination = destination;
+ strcpy(io_name, fOutput.name);
+
+ if (fOutput.format.u.raw_video.field_rate != 0.0f) {
+ fPerformanceTimeBase = fPerformanceTimeBase +
+ (bigtime_t)
+ ((fFrame - fFrameBase) *
+ (1000000 / fOutput.format.u.raw_video.field_rate));
+ fFrameBase = fFrame;
+ }
+
+ fConnectedFormat = format.u.raw_video;
+
+ /* get the latency */
+ bigtime_t latency = 0;
+ media_node_id tsID = 0;
+ FindLatencyFor(fOutput.destination, &latency, &tsID);
+ #define NODE_LATENCY 1000
+ SetEventLatency(latency + NODE_LATENCY);
+
+ uint32 *buffer, *p, f = 3;
+ p = buffer = (uint32 *)malloc(4 * fConnectedFormat.display.line_count *
+ fConnectedFormat.display.line_width);
+ if (!buffer) {
+ PRINTF(0, ("Connect: Out of memory\n"));
+ return;
+ }
+ bigtime_t now = system_time();
+ for (int y=0;yInitCheck() < B_OK) {
+ delete fBufferGroup;
+ fBufferGroup = NULL;
+ return;
+ }
+
+ fConnected = true;
+ fEnabled = true;
+
+ /* Tell frame generation thread to recalculate delay value */
+ release_sem(fFrameSync);
+}
+
+void
+VideoProducer::Disconnect(const media_source &source,
+ const media_destination &destination)
+{
+ PRINTF(1, ("Disconnect()\n"));
+
+ if (!fConnected) {
+ PRINTF(0, ("Disconnect: Not connected\n"));
+ return;
+ }
+
+ if ((source != fOutput.source) || (destination != fOutput.destination)) {
+ PRINTF(0, ("Disconnect: Bad source and/or destination\n"));
+ return;
+ }
+
+ fEnabled = false;
+ fOutput.destination = media_destination::null;
+
+ fLock.Lock();
+ delete fBufferGroup;
+ fBufferGroup = NULL;
+ fLock.Unlock();
+
+ fConnected = false;
+}
+
+void
+VideoProducer::LateNoticeReceived(const media_source &source,
+ bigtime_t how_much, bigtime_t performance_time)
+{
+ TOUCH(source); TOUCH(how_much); TOUCH(performance_time);
+}
+
+void
+VideoProducer::EnableOutput(const media_source &source, bool enabled,
+ int32 *_deprecated_)
+{
+ TOUCH(_deprecated_);
+
+ if (source != fOutput.source)
+ return;
+
+ fEnabled = enabled;
+}
+
+status_t
+VideoProducer::SetPlayRate(int32 numer, int32 denom)
+{
+ TOUCH(numer); TOUCH(denom);
+
+ return B_ERROR;
+}
+
+void
+VideoProducer::AdditionalBufferRequested(const media_source &source,
+ media_buffer_id prev_buffer, bigtime_t prev_time,
+ const media_seek_tag *prev_tag)
+{
+ TOUCH(source); TOUCH(prev_buffer); TOUCH(prev_time); TOUCH(prev_tag);
+}
+
+void
+VideoProducer::LatencyChanged(const media_source &source,
+ const media_destination &destination, bigtime_t new_latency,
+ uint32 flags)
+{
+ TOUCH(source); TOUCH(destination); TOUCH(new_latency); TOUCH(flags);
+}
+
+/* BControllable */
+
+status_t
+VideoProducer::GetParameterValue(
+ int32 id, bigtime_t *last_change, void *value, size_t *size)
+{
+ switch(id){
+ case P_CHANNEL:
+ *last_change = fLastChannelChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fChannel;
+ break;
+ case P_VIDEO_INPUT:
+ *last_change = fLastVideoInputChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fVideoInput;
+ break;
+ case P_AUDIO_INPUT:
+ *last_change = fLastAudioInputChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fAudioInput;
+ break;
+ case P_BRIGHTNESS:
+ *last_change = fLastBrightnessChange;
+ *size = sizeof(float);
+ *((float *)value) = fBrightness;
+ break;
+ case P_CONTRAST:
+ *last_change = fLastContrastChange;
+ *size = sizeof(float);
+ *((float*)value) = fContrast;
+ break;
+ case P_SATURATION:
+ *last_change = fLastSaturationChange;
+ *size = sizeof(float);
+ *((float*)value) = fSaturation;
+ break;
+ case P_HUE:
+ *last_change = fLastHueChange;
+ *size = sizeof(float);
+ *((float*)value) = fHue;
+ break;
+ case P_CAPTURE_SIZE:
+ *last_change = fLastCaptureSizeChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fCaptureSize;
+ break;
+ case P_CAPTURE_FORMAT:
+ *last_change = fLastCaptureFormatChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fCaptureFormat;
+ break;
+ case P_STANDART:
+ *last_change = fLastStandardChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fStandard;
+ break;
+ case P_BANDWIDTH:
+ *last_change = fLastBandwidthChange;
+ *size = sizeof(float);
+ *((float *)value) = fBandwidth;
+ break;
+ case P_LOCALE:
+ *last_change = fLastLocaleChange;
+ *size = sizeof(uint32);
+ *((uint32*)value) = fLocale;
+ break;
+ case P_VERT_OFFSET:
+ *last_change = fLastVertOffsetChange;
+ *size = sizeof(float);
+ *((float*)value) = fVertOffset;
+ break;
+ case P_HORZ_OFFSET:
+ *last_change = fLastHorzOffsetChange;
+ *size = sizeof(float);
+ *((float*)value) = fHorzOffset;
+ break;
+ case P_COLOR:
+ *last_change = fLastColorChange;
+ *size = sizeof(uint32);
+ *((uint32 *)value) = fColor;
+ break;
+ default:
+ return B_BAD_VALUE;
+ }
+ return B_OK;
+}
+
+void
+VideoProducer::SetParameterValue(
+ int32 id, bigtime_t when, const void *value, size_t size)
+{
+ switch(id){
+ case P_CHANNEL:
+ if (*(uint32 *)value != fChannel){
+ fChannel = *(uint32 *)value;
+ fLastChannelChange = when;
+ BroadcastNewParameterValue(
+ fLastChannelChange, P_CHANNEL, &fChannel, sizeof(fChannel));
+ }
+ break;
+ case P_VIDEO_INPUT:
+ if (*(uint32 *)value != fVideoInput){
+ fVideoInput = *(uint32 *)value;
+ fLastVideoInputChange = when;
+ BroadcastNewParameterValue(
+ fLastVideoInputChange, P_VIDEO_INPUT, &fVideoInput, sizeof(fVideoInput));
+ }
+ break;
+ case P_AUDIO_INPUT:
+ if (*(uint32 *)value != fAudioInput){
+ fAudioInput = *(uint32 *)value;
+ fLastAudioInputChange = when;
+ BroadcastNewParameterValue(
+ fLastAudioInputChange, P_AUDIO_INPUT, &fAudioInput, sizeof(fAudioInput));
+ }
+ break;
+ case P_BRIGHTNESS:
+ if (*(float *)value != fBrightness){
+ fBrightness = *(float *)value;
+ fLastBrightnessChange = when;
+ BroadcastNewParameterValue(
+ fLastBrightnessChange, P_BRIGHTNESS, &fBrightness, sizeof(fBrightness));
+ }
+ break;
+ case P_CONTRAST:
+ if (*(float *)value != fContrast){
+ fContrast = *(float *)value;
+ fLastContrastChange = when;
+ BroadcastNewParameterValue(
+ fLastContrastChange, P_CONTRAST, &fContrast, sizeof(fContrast));
+ }
+ break;
+ case P_SATURATION:
+ if (*(float *)value != fSaturation){
+ fSaturation = *(float *)value;
+ fLastSaturationChange = when;
+ BroadcastNewParameterValue(
+ fLastSaturationChange, P_SATURATION, &fSaturation, sizeof(fSaturation));
+ }
+ break;
+ case P_HUE:
+ if (*(float *)value != fHue){
+ fHue = *(float *)value;
+ fLastHueChange = when;
+ BroadcastNewParameterValue(
+ fLastHueChange, P_HUE, &fHue, sizeof(fHue));
+ }
+ break;
+ case P_CAPTURE_SIZE:
+ if (*(uint32 *)value != fCaptureSize){
+ fCaptureSize = *(uint32*)value;
+ fLastCaptureSizeChange = when;
+ BroadcastNewParameterValue(
+ fLastCaptureSizeChange, P_CAPTURE_SIZE, &fCaptureSize, sizeof(fCaptureSize));
+ }
+ break;
+ case P_CAPTURE_FORMAT:
+ if (*(uint32 *)value != fCaptureFormat){
+ fCaptureFormat = *(uint32*)value;
+ fLastCaptureFormatChange = when;
+ BroadcastNewParameterValue(
+ fLastCaptureFormatChange, P_CAPTURE_FORMAT, &fCaptureFormat, sizeof(fCaptureFormat));
+ }
+ break;
+ case P_STANDART:
+ if (*(uint32 *)value != fStandard){
+ fStandard = *(uint32*)value;
+ fLastStandardChange = when;
+ BroadcastNewParameterValue(
+ fLastStandardChange, P_STANDART, &fStandard, sizeof(fStandard));
+ }
+ break;
+ case P_BANDWIDTH:
+ if (*(float *)value != fBandwidth){
+ fBandwidth = *(float *)value;
+ fLastBandwidthChange = when;
+ BroadcastNewParameterValue(
+ fLastBandwidthChange, P_BANDWIDTH, &fBandwidth, sizeof(fBandwidth));
+ }
+ break;
+ case P_LOCALE:
+ if (*(uint32 *)value != fLocale){
+ fLocale = *(uint32 *)value;
+ fLastLocaleChange = when;
+ BroadcastNewParameterValue(
+ fLastLocaleChange, P_LOCALE, &fLocale, sizeof(fLocale));
+ }
+ break;
+ case P_VERT_OFFSET:
+ if (*(float*)value != fVertOffset){
+ fVertOffset = *(float *)value;
+ fLastVertOffsetChange = when;
+ BroadcastNewParameterValue(
+ fLastVertOffsetChange, P_VERT_OFFSET, &fVertOffset, sizeof(fVertOffset));
+ }
+ break;
+ case P_HORZ_OFFSET:
+ if (*(float*)value != fHorzOffset){
+ fHorzOffset = *(float *)value;
+ fLastHorzOffsetChange = when;
+ BroadcastNewParameterValue(
+ fLastHorzOffsetChange, P_HORZ_OFFSET, &fHorzOffset, sizeof(fHorzOffset));
+ }
+ break;
+ case P_COLOR:
+ if (*(int32 *)value != fColor){
+ fColor = *(uint32 *)value;
+ fLastColorChange = when;
+ BroadcastNewParameterValue(
+ fLastColorChange, P_COLOR, &fColor, sizeof(fColor));
+ }
+ break;
+ }
+
+ EventQueue()->AddEvent(media_timed_event(when,
+ BTimedEventQueue::B_PARAMETER, NULL,
+ BTimedEventQueue::B_NO_CLEANUP, id, 0, NULL, 0));
+
+}
+
+status_t
+VideoProducer::StartControlPanel(BMessenger *out_messenger)
+{
+ return BControllable::StartControlPanel(out_messenger);
+}
+
+/* VideoProducer */
+
+void
+VideoProducer::HandleStart(bigtime_t performance_time)
+{
+ /* Start producing frames, even if the output hasn't been connected yet. */
+
+ PRINTF(1, ("HandleStart(%Ld)\n", performance_time));
+
+ if (fRunning) {
+ PRINTF(-1, ("HandleStart: Node already started\n"));
+ return;
+ }
+
+ fFrame = 0;
+ fFrameBase = 0;
+ fPerformanceTimeBase = performance_time;
+
+ fFrameSync = create_sem(0, "frame synchronization");
+ if (fFrameSync < B_OK)
+ goto err1;
+
+ fThread = spawn_thread(_frame_generator_, "frame generator",
+ B_NORMAL_PRIORITY, this);
+ if (fThread < B_OK)
+ goto err2;
+
+ resume_thread(fThread);
+
+ fRunning = true;
+ return;
+
+err2:
+ delete_sem(fFrameSync);
+err1:
+ return;
+}
+
+void
+VideoProducer::HandleStop(void)
+{
+ PRINTF(1, ("HandleStop()\n"));
+
+ if (!fRunning) {
+ PRINTF(-1, ("HandleStop: Node isn't running\n"));
+ return;
+ }
+
+ delete_sem(fFrameSync);
+ wait_for_thread(fThread, &fThread);
+
+ fRunning = false;
+}
+
+void
+VideoProducer::HandleTimeWarp(bigtime_t performance_time)
+{
+ fPerformanceTimeBase = performance_time;
+ fFrameBase = fFrame;
+
+ /* Tell frame generation thread to recalculate delay value */
+ release_sem(fFrameSync);
+}
+
+void
+VideoProducer::HandleSeek(bigtime_t performance_time)
+{
+ fPerformanceTimeBase = performance_time;
+ fFrameBase = fFrame;
+
+ /* Tell frame generation thread to recalculate delay value */
+ release_sem(fFrameSync);
+}
+
+void
+VideoProducer::HandleParameter(uint32 parameter)
+{
+ switch(parameter){
+ case P_CHANNEL:
+ break;
+ case P_VIDEO_INPUT:
+ break;
+ case P_AUDIO_INPUT:
+ break;
+ case P_BRIGHTNESS:
+ break;
+ case P_CONTRAST:
+ break;
+ case P_SATURATION:
+ break;
+ case P_HUE:
+ break;
+ case P_CAPTURE_SIZE:
+ break;
+ case P_CAPTURE_FORMAT:
+ break;
+ case P_STANDART:
+ break;
+ case P_BANDWIDTH:
+ break;
+ case P_LOCALE:
+ {
+ //debugger("stop");
+ BParameterWeb *web = Web();
+ int nCount = web->CountParameters();
+ for(int idx = 0; idx < nCount; idx++){
+ BParameter *parameter = web->ParameterAt(idx);
+ if(parameter && parameter->Type() == BParameter::B_DISCRETE_PARAMETER &&
+ parameter->ID() == P_CHANNEL){
+ BDiscreteParameter * d_parameter = dynamic_cast(parameter);
+ d_parameter->MakeEmpty();
+ for(int i = 0; i < fLocales[fLocale]->ChannelsCount(); i ++){
+ d_parameter->AddItem(i, (fLocales[fLocale]->GetChannel(i)).Name().c_str());
+ }
+ /*status_t st = BroadcastChangedParameter(P_CHANNEL);
+ if(st != B_OK)
+ debugger("kk");*/
+ break;
+ }
+ }
+ }
+ break;
+ case P_VERT_OFFSET:
+ break;
+ case P_HORZ_OFFSET:
+ break;
+ }
+}
+
+/* The following functions form the thread that generates frames. You should
+ * replace this with the code that interfaces to your hardware. */
+int32
+VideoProducer::FrameGenerator()
+{
+ bigtime_t wait_until = system_time();
+
+ while (1) {
+ status_t err = acquire_sem_etc(fFrameSync, 1, B_ABSOLUTE_TIMEOUT,
+ wait_until);
+
+ /* The only acceptable responses are B_OK and B_TIMED_OUT. Everything
+ * else means the thread should quit. Deleting the semaphore, as in
+ * VideoProducer::HandleStop(), will trigger this behavior. */
+ if ((err != B_OK) && (err != B_TIMED_OUT))
+ break;
+
+ fFrame++;
+
+ /* Recalculate the time until the thread should wake up to begin
+ * processing the next frame. Subtract fProcessingLatency so that
+ * the frame is sent in time. */
+ wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase +
+ (bigtime_t)
+ ((fFrame - fFrameBase) *
+ (1000000 / fConnectedFormat.field_rate)), 0) -
+ fProcessingLatency;
+
+ /* Drop frame if it's at least a frame late */
+ if (wait_until < system_time())
+ continue;
+
+ /* If the semaphore was acquired successfully, it means something
+ * changed the timing information (see VideoProducer::Connect()) and
+ * so the thread should go back to sleep until the newly-calculated
+ * wait_until time. */
+ if (err == B_OK)
+ continue;
+
+ /* Send buffers only if the node is running and the output has been
+ * enabled */
+ if (!fRunning || !fEnabled)
+ continue;
+
+ BAutolock _(fLock);
+
+ /* Fetch a buffer from the buffer group */
+ BBuffer *buffer = fBufferGroup->RequestBuffer(
+ 4 * fConnectedFormat.display.line_width *
+ fConnectedFormat.display.line_count, 0LL);
+ if (!buffer)
+ continue;
+
+ /* Fill out the details about this buffer. */
+ media_header *h = buffer->Header();
+ h->type = B_MEDIA_RAW_VIDEO;
+ h->time_source = TimeSource()->ID();
+ h->size_used = 4 * fConnectedFormat.display.line_width *
+ fConnectedFormat.display.line_count;
+ /* For a buffer originating from a device, you might want to calculate
+ * this based on the PerformanceTimeFor the time your buffer arrived at
+ * the hardware (plus any applicable adjustments). */
+ h->start_time = fPerformanceTimeBase +
+ (bigtime_t)
+ ((fFrame - fFrameBase) *
+ (1000000 / fConnectedFormat.field_rate));
+ h->file_pos = 0;
+ h->orig_size = 0;
+ h->data_offset = 0;
+ h->u.raw_video.field_gamma = 1.0;
+ h->u.raw_video.field_sequence = fFrame;
+ h->u.raw_video.field_number = 0;
+ h->u.raw_video.pulldown_number = 0;
+ h->u.raw_video.first_active_line = 1;
+ h->u.raw_video.line_count = fConnectedFormat.display.line_count;
+
+ /* Fill in a pattern */
+ uint32 *p = (uint32 *)buffer->Data();
+ for (int y=0;yRecycle();
+ }
+ }
+
+ return B_OK;
+}
+
+int32
+VideoProducer::_frame_generator_(void *data)
+{
+ return ((VideoProducer *)data)->FrameGenerator();
+}
diff --git a/src/add-ons/media/media-add-ons/usb_vision/Producer.h b/src/add-ons/media/media-add-ons/usb_vision/Producer.h
new file mode 100644
index 0000000000..30ebd3a5c7
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/Producer.h
@@ -0,0 +1,208 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ * Skeletal part of this code was inherired from original BeOS sample code,
+ * that is distributed under the terms of the Be Sample Code License.
+ *
+ */
+
+#ifndef _USBVISION_PRODUCER_H
+#define _USBVISION_PRODUCER_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "TunerLocale.h"
+
+class VideoProducer :
+ public virtual BMediaEventLooper,
+ public virtual BBufferProducer,
+ public virtual BControllable
+{
+public:
+ VideoProducer(BMediaAddOn *addon,
+ const char *name, int32 internal_id);
+virtual ~VideoProducer();
+
+virtual status_t InitCheck() const { return fInitStatus; }
+
+/* BMediaNode */
+public:
+virtual port_id ControlPort() const;
+virtual BMediaAddOn *AddOn(int32 * internal_id) const;
+virtual status_t HandleMessage(int32 message, const void *data,
+ size_t size);
+protected:
+virtual void Preroll();
+virtual void SetTimeSource(BTimeSource * time_source);
+virtual status_t RequestCompleted(const media_request_info & info);
+
+/* BMediaEventLooper */
+protected:
+virtual void NodeRegistered();
+virtual void Start(bigtime_t performance_time);
+virtual void Stop(bigtime_t performance_time, bool immediate);
+virtual void Seek(bigtime_t media_time, bigtime_t performance_time);
+virtual void TimeWarp(bigtime_t at_real_time,
+ bigtime_t to_performance_time);
+virtual status_t AddTimer(bigtime_t at_performance_time, int32 cookie);
+virtual void SetRunMode(run_mode mode);
+virtual void HandleEvent(const media_timed_event *event,
+ bigtime_t lateness, bool realTimeEvent = false);
+virtual void CleanUpEvent(const media_timed_event *event);
+virtual bigtime_t OfflineTime();
+virtual void ControlLoop();
+virtual status_t DeleteHook(BMediaNode * node);
+
+/* BBufferProducer */
+protected:
+virtual status_t FormatSuggestionRequested(media_type type, int32 quality,
+ media_format * format);
+virtual status_t FormatProposal(const media_source &output,
+ media_format *format);
+virtual status_t FormatChangeRequested(const media_source &source,
+ const media_destination &destination,
+ media_format *io_format, int32 *_deprecated_);
+virtual status_t GetNextOutput(int32 * cookie, media_output * out_output);
+virtual status_t DisposeOutputCookie(int32 cookie);
+virtual status_t SetBufferGroup(const media_source &for_source,
+ BBufferGroup * group);
+virtual status_t VideoClippingChanged(const media_source &for_source,
+ int16 num_shorts, int16 *clip_data,
+ const media_video_display_info &display,
+ int32 * _deprecated_);
+virtual status_t GetLatency(bigtime_t * out_latency);
+virtual status_t PrepareToConnect(const media_source &what,
+ const media_destination &where,
+ media_format *format,
+ media_source *out_source, char *out_name);
+virtual void Connect(status_t error, const media_source &source,
+ const media_destination &destination,
+ const media_format & format, char *io_name);
+virtual void Disconnect(const media_source & what,
+ const media_destination & where);
+virtual void LateNoticeReceived(const media_source & what,
+ bigtime_t how_much, bigtime_t performance_time);
+virtual void EnableOutput(const media_source & what, bool enabled,
+ int32 * _deprecated_);
+virtual status_t SetPlayRate(int32 numer,int32 denom);
+virtual void AdditionalBufferRequested(const media_source & source,
+ media_buffer_id prev_buffer, bigtime_t prev_time,
+ const media_seek_tag * prev_tag);
+virtual void LatencyChanged(const media_source & source,
+ const media_destination & destination,
+ bigtime_t new_latency, uint32 flags);
+
+/* BControllable */
+protected:
+virtual status_t GetParameterValue(int32 id, bigtime_t *last_change,
+ void *value, size_t *size);
+virtual void SetParameterValue(int32 id, bigtime_t when,
+ const void *value, size_t size);
+virtual status_t StartControlPanel(BMessenger *out_messenger);
+
+/* state */
+private:
+ void HandleStart(bigtime_t performance_time);
+ void HandleStop();
+ void HandleTimeWarp(bigtime_t performance_time);
+ void HandleSeek(bigtime_t performance_time);
+ void HandleParameter(uint32 parameter);
+
+static int32 fInstances;
+
+ status_t fInitStatus;
+
+ int32 fInternalID;
+ BMediaAddOn *fAddOn;
+
+ BLocker fLock;
+ BBufferGroup *fBufferGroup;
+
+ thread_id fThread;
+ sem_id fFrameSync;
+static int32 _frame_generator_(void *data);
+ int32 FrameGenerator();
+
+ /* The remaining variables should be declared volatile, but they
+ * are not here to improve the legibility of the sample code. */
+ uint32 fFrame;
+ uint32 fFrameBase;
+ bigtime_t fPerformanceTimeBase;
+ bigtime_t fProcessingLatency;
+ media_output fOutput;
+ media_raw_video_format fConnectedFormat;
+ bool fRunning;
+ bool fConnected;
+ bool fEnabled;
+
+ enum { P_CHANNEL,
+ P_VIDEO_INPUT,
+ P_AUDIO_INPUT,
+ P_BRIGHTNESS,
+ P_CONTRAST,
+ P_SATURATION,
+ P_HUE,
+ P_CAPTURE_SIZE,
+ P_CAPTURE_FORMAT,
+ P_STANDART,
+ P_BANDWIDTH,
+ P_LOCALE,
+ P_VERT_OFFSET,
+ P_HORZ_OFFSET,
+ P_COLOR };
+enum { P_VI_TUNER,
+ P_VI_COMPOSITE,
+ P_VI_SVIDEO};
+enum { P_VF_NTSC_M,
+ P_VF_NTSC_MJ,
+ P_VF_PAL_BDGHI,
+ P_VF_PAL_M,
+ P_VF_PAL_N,
+ P_VF_SECAM};
+ BParameterWeb *CreateParameterWeb();
+
+ uint32 fChannel;
+ bigtime_t fLastChannelChange;
+ uint32 fVideoInput;
+ bigtime_t fLastVideoInputChange;
+ uint32 fAudioInput;
+ bigtime_t fLastAudioInputChange;
+ float fBrightness;
+ bigtime_t fLastBrightnessChange;
+ float fContrast;
+ bigtime_t fLastContrastChange;
+ float fSaturation;
+ bigtime_t fLastSaturationChange;
+ float fHue;
+ bigtime_t fLastHueChange;
+ uint32 fCaptureSize;
+ bigtime_t fLastCaptureSizeChange;
+ uint32 fCaptureFormat;
+ bigtime_t fLastCaptureFormatChange;
+ uint32 fStandard;
+ bigtime_t fLastStandardChange;
+ float fBandwidth;
+ bigtime_t fLastBandwidthChange;
+ uint32 fLocale;
+ bigtime_t fLastLocaleChange;
+ float fVertOffset;
+ bigtime_t fLastVertOffsetChange;
+ float fHorzOffset;
+ bigtime_t fLastHorzOffsetChange;
+
+ uint32 fColor;
+ bigtime_t fLastColorChange;
+
+ Locale::Locales fLocales;
+};
+
+#endif /*_USBVISION_PRODUCER_H*/
diff --git a/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp
new file mode 100644
index 0000000000..b60e1327cc
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.cpp
@@ -0,0 +1,135 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+
+#include "TunerLocale.h"
+
+using namespace Locale;
+
+const char *kLocalesSettings = "media/usb_vision/Locales";
+
+Channel::Channel(string &str, uint32 frequency):
+ fName(str), fFrequency(frequency)
+{
+}
+
+const string &Channel::Name() const
+{
+ return fName;
+}
+const uint32 Channel::Frequency()
+{
+ return fFrequency;
+}
+
+TunerLocale::TunerLocale(BEntry &entry)
+{
+ fStatus = B_NO_INIT;
+ if(entry.IsFile()){
+ BPath path;
+ if((fStatus = entry.GetPath(&path)) == B_OK){
+ char name[B_FILE_NAME_LENGTH];
+ if((fStatus = entry.GetName(name)) == B_OK){
+ fName = name;
+ fStatus = LoadLocale(path.Path());
+ }
+ }
+ }
+}
+
+TunerLocale::~TunerLocale()
+{
+}
+
+status_t TunerLocale::InitCheck()
+{
+ return fStatus;
+}
+
+status_t TunerLocale::LoadLocale(const char *name)
+{
+ status_t status = B_OK;
+ ifstream ifs(name);
+ while(ifs.good() && !ifs.eof()){
+ string str;
+ getline(ifs, str);
+ //TODO : validity check and parse strings ...
+ str.erase(0, str.find_first_not_of(" \t"));
+ str.erase(str.find_last_not_of(" \t") + 1);
+ switch(str[0]){
+ case ';': continue;
+ case '@':
+ str.erase(0, 1);
+ fName = str;
+ break;
+ default: //TODO parse ...
+ Channel channel(str, 0);
+ fChannels.push_back(channel);
+ break;
+ }
+ }
+ return status;
+}
+
+status_t TunerLocale::LoadLocales(vector &vector)
+{
+ status_t status = B_ERROR;
+ BPath path;
+ if((status = find_directory(B_USER_SETTINGS_DIRECTORY, &path)) != B_OK)
+ return status;
+ if((status = path.Append(kLocalesSettings)) != B_OK)
+ return status;
+ BDirectory directory(path.Path());
+ if((status = directory.InitCheck()) != B_OK)
+ return status;
+ vector.clear();
+ BEntry entry;
+ while((status = directory.GetNextEntry(&entry)) == B_OK){
+ if(entry.IsFile()){
+ TunerLocale *locale = new TunerLocale(entry);
+ if((status = locale->InitCheck()) == B_OK){
+ vector.push_back(locale);
+ }
+ else
+ delete locale;
+ }
+ }
+ if(status == B_ENTRY_NOT_FOUND) //we reached the end of entries list ...
+ status = B_OK;
+ return status;
+}
+
+status_t TunerLocale::ReleaseLocales(vector &vector)
+{
+ for(LocalesIterator locale = vector.begin();
+ locale != vector.end(); locale ++){
+ delete *locale;
+ }
+ return B_OK;
+}
+
+const string &TunerLocale::Name()
+{
+ return fName;
+}
+
+const Channel &TunerLocale::GetChannel(int idx)
+{
+ if(idx < 0) idx = 0;
+ if(idx >= (int)fChannels.size()) idx = (int)(fChannels.size() - 1);
+ return fChannels[idx];
+}
+
+uint32 TunerLocale::ChannelsCount()
+{
+ return fChannels.size();
+}
diff --git a/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h
new file mode 100644
index 0000000000..b2eff8f447
--- /dev/null
+++ b/src/add-ons/media/media-add-ons/usb_vision/TunerLocale.h
@@ -0,0 +1,51 @@
+/*
+ * This file is a part of BeOS USBVision driver project.
+ * Copyright (c) 2003 by Siarzuk Zharski
+ *
+ * This file may be used under the terms of the BSD License
+ *
+ */
+#ifndef _TUNER_LOCALE_H_
+ #define _TUNER_LOCALE_H_
+
+#include
+#include
+
+namespace Locale{
+
+class Channel
+{
+ string fName;
+ uint32 fFrequency;
+public:
+ Channel(string &str, uint32 frequency);
+ const string &Name() const;
+ const uint32 Frequency();
+};
+
+typedef vector Channels;
+typedef vector::iterator ChannelsIterator;
+
+class TunerLocale
+{
+ status_t fStatus;
+ string fName;
+ Channels fChannels;
+ TunerLocale(BEntry &entry);
+ status_t LoadLocale(const char *file);
+public:
+ ~TunerLocale();
+ static status_t LoadLocales(vector &vector);
+ static status_t ReleaseLocales(vector &vector);
+ status_t InitCheck();
+ const string &Name();
+ const Channel &GetChannel(int idx);
+ uint32 ChannelsCount();
+};
+
+typedef vector Locales;
+typedef vector::iterator LocalesIterator;
+
+} //namespace Locale
+
+#endif//_TUNER_LOCALE_H_
diff --git a/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp b/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp
index 13be6ba64a..76ce841f2f 100644
--- a/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp
+++ b/src/add-ons/media/media-add-ons/video_producer_demo/Producer.cpp
@@ -656,10 +656,10 @@ VideoProducer::FrameGenerator()
/* Recalculate the time until the thread should wake up to begin
* processing the next frame. Subtract fProcessingLatency so that
* the frame is sent in time. */
- wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase, 0) +
+ wait_until = TimeSource()->RealTimeFor(fPerformanceTimeBase +
(bigtime_t)
((fFrame - fFrameBase) *
- (1000000 / fConnectedFormat.field_rate)) -
+ (1000000 / fConnectedFormat.field_rate)), 0) -
fProcessingLatency;
/* Drop frame if it's at least a frame late */