📄 driver.c
字号:
/* * This file is a part of BeOS USB Serial driver project. * Copyright (c) 2003 by Siarzuk Zharski <imker@gmx.li> * * This file may be used under the terms of the BSD License * See the file "License" for details. * * $Source: /cvsroot/sis4be/usb_serial/driver.c,v $ * $Author: zharik $ * $Revision: 1.8 $ * $Date: 2003/10/05 17:44:52 $ * */ #include <KernelExport.h>#include <Drivers.h>#include <USB.h>#include <ttylayer.h>#include <malloc.h>#include <string.h> /* strerror */#include <stdlib.h> /* strtol */#include <stdio.h> /* 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_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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -