📄 driver.c
字号:
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<DEVICES_COUNT;i++) TRACE("%08x\n",usb_serial_devices[i]); *cookie = NULL; i = strtol(name + BASENAME_LEN, NULL, 10); if(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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -