static status_t usb_disk_prepare_partial_buffer(device_lun *lun, off_t position, size_t length, void *&partialBuffer, void *&blockBuffer, uint32 &blockPosition, uint16 &blockCount) { blockPosition = (uint32)(position / lun->block_size); blockCount = (uint16)((uint32)((position + length + lun->block_size - 1) / lun->block_size) - blockPosition); size_t blockLength = blockCount * lun->block_size; blockBuffer = malloc(blockLength); if (blockBuffer == NULL) { TRACE_ALWAYS("no memory to allocate partial buffer\n"); return B_NO_MEMORY; } status_t result = usb_disk_block_read(lun, blockPosition, blockCount, blockBuffer, &blockLength); if (result != B_OK) { TRACE_ALWAYS("block read failed when filling partial buffer\n"); free(blockBuffer); return result; } off_t offset = position - (blockPosition * lun->block_size); partialBuffer = (uint8 *)blockBuffer + offset; return B_OK; }
DavicomDevice * lookup_and_create_device(usb_device device) { const usb_device_descriptor *deviceDescriptor = gUSBModule->get_device_descriptor(device); if (deviceDescriptor == NULL) { TRACE_ALWAYS("Error of getting USB device descriptor.\n"); return NULL; } TRACE("trying %#06x:%#06x.\n", deviceDescriptor->vendor_id, deviceDescriptor->product_id); // use binary search to lookup device in table uint32 id = deviceDescriptor->vendor_id << 16 | deviceDescriptor->product_id; int left = -1; int right = B_COUNT_OF(gSupportedDevices); while ((right - left) > 1) { int i = (left + right) / 2; ((gSupportedDevices[i].Key() < id) ? left : right) = i; } if (gSupportedDevices[right].Key() == id) return new DavicomDevice(device, gSupportedDevices[right]); TRACE_ALWAYS("Search for %#x failed %d-%d.\n", id, left, right); return NULL; }
status_t AX88772Device::StartDevice() { size_t actualLength = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_IPGS, 0, 0, sizeof(fIPG), fIPG, &actualLength); if(result != B_OK) { TRACE_ALWAYS("Error of writing IPGs:%#010x\n", result); return result; } if(actualLength != sizeof(fIPG)) { TRACE_ALWAYS("Mismatch of written IPGs data. " "%d bytes of %d written.\n", actualLength, sizeof(fIPG)); } uint16 rxcontrol = RXCTL_START | RXCTL_MULTICAST | RXCTL_BROADCAST; result = WriteRXControlRegister(rxcontrol); if(result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); } TRACE_RET(result); return result; }
status_t my_modeswitch(my_device* device) { status_t err = B_OK; if (device->type[0] == MSG_NONE) return B_OK; for (int i = 0; i < 3; i++) { if (device->type[i] == MSG_NONE) break; err = my_transfer_data(device, false, kDevicesMsg[device->type[i]], sizeof(kDevicesMsg[device->type[i]])); if (err != B_OK) { TRACE_ALWAYS("send message %d failed\n", i + 1); return err; } TRACE("device switched: %p\n", device); char data[36]; err = my_transfer_data(device, true, data, sizeof(data)); if (err != B_OK) { TRACE_ALWAYS("receive response %d failed 0x%" B_PRIx32 "\n", i + 1, device->status); return err; } TRACE("device switched (response length %ld)\n", device->actual_length); } TRACE("device switched: %p\n", device); return B_OK; }
status_t ASIXDevice::SetPromiscuousMode(bool on) { uint16 rxcontrol = 0; status_t result = ReadRXControlRegister(&rxcontrol); if (result != B_OK) { TRACE_ALWAYS("Error of reading RX Control:%#010x\n", result); return result; } if (on) rxcontrol |= RXCTL_PROMISCUOUS; else rxcontrol &= ~RXCTL_PROMISCUOUS; result = WriteRXControlRegister(rxcontrol); if (result != B_OK ) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", rxcontrol, result); } TRACE_RET(result); return result; }
status_t AX88772Device::_SetupAX88772B() { // Reload EEPROM size_t actualLength = 0; status_t result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_GPIOS, GPIO_RSE, 0, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of reloading EEPROM: %#010x\n", result); return result; } result = _WakeupPHY(); if (result != B_OK) return result; result = WriteRXControlRegister(0); if (result != B_OK) { TRACE_ALWAYS("Error of writing %#04x RX Control:%#010x\n", 0, result); return result; } fIPG[0] = 0x15; fIPG[1] = 0x16; fIPG[2] = 0x1A; return B_OK; }
void HIDReport::PrintToStream() { TRACE_ALWAYS("HIDReport %p\n", this); const char *typeName = "unknown"; switch (fType) { case HID_REPORT_TYPE_INPUT: typeName = "input"; break; case HID_REPORT_TYPE_OUTPUT: typeName = "output"; break; case HID_REPORT_TYPE_FEATURE: typeName = "feature"; break; } TRACE_ALWAYS("\ttype: %u %s\n", fType, typeName); TRACE_ALWAYS("\treport id: %u\n", fReportID); TRACE_ALWAYS("\treport size: %" B_PRIu32 " bits = %" B_PRIu32 " bytes\n", fReportSize, (fReportSize + 7) / 8); TRACE_ALWAYS("\titem count: %" B_PRIu32 "\n", fItemsUsed); for (uint32 i = 0; i < fItemsUsed; i++) { HIDReportItem *item = fItems[i]; if (item != NULL) item->PrintToStream(1); } }
status_t init_driver() { status_t status = get_module(B_PCI_MODULE_NAME, (module_info**)&gPCIModule); if (status < B_OK) { return ENOSYS; } load_settings(); TRACE_ALWAYS("%s\n", kVersion); pci_info info = {0}; for (long i = 0; B_OK == (*gPCIModule->get_nth_pci_info)(i, &info); i++) { for (size_t idx = 0; idx < _countof(cardInfos); idx++) { if (info.vendor_id == cardInfos[idx].VendorId() && info.device_id == cardInfos[idx].DeviceId()) { TRACE_ALWAYS("Found:%s %#010x\n", cardInfos[idx].Description(), cardInfos[idx].Id()); if (numCards == MAX_DEVICES) { break; } Device* device = new Device(cardInfos[idx], info); if (device == 0) { return ENODEV; } status_t status = device->InitCheck(); if (status < B_OK) { delete device; break; } status = device->SetupDevice(); if (status < B_OK) { delete device; break; } char name[DEVNAME_LEN] = {0}; sprintf(name, "net/%s/%ld", cardInfos[idx].Name(), numCards); gDeviceNames[numCards] = strdup(name); gDevices[numCards++] = device; } } } if (numCards == 0) { put_module(B_PCI_MODULE_NAME); return ENODEV; } add_debugger_command(DRIVER_NAME, SiS19X_DebuggerCommand, "SiS190/191 Ethernet driver info"); return B_OK; }
void ASIXDevice::_NotifyCallback(void *cookie, int32 status, void *data, uint32 actualLength) { ASIXDevice *device = (ASIXDevice *)cookie; atomic_add(&device->fInsideNotify, 1); if (status == B_CANCELED || device->fRemoved) { atomic_add(&device->fInsideNotify, -1); return; } if (status != B_OK) { TRACE_ALWAYS("Device status error:%#010x\n", status); status_t result = gUSBModule->clear_feature(device->fNotifyEndpoint, USB_FEATURE_ENDPOINT_HALT); if (result != B_OK) TRACE_ALWAYS("Error during clearing of HALT state:%#010x.\n", result); } // parse data in overriden class device->OnNotify(actualLength); // schedule next notification buffer gUSBModule->queue_interrupt(device->fNotifyEndpoint, device->fNotifyBuffer, device->fNotifyBufferLength, _NotifyCallback, device); atomic_add(&device->fInsideNotify, -1); }
status_t usb_disk_inquiry(device_lun *lun) { uint32 dataLength = sizeof(scsi_inquiry_6_parameter); scsi_inquiry_6_parameter parameter; status_t result = B_ERROR; for (uint32 tries = 0; tries < 3; tries++) { result = usb_disk_operation(lun, SCSI_INQUIRY_6, 6, 0, dataLength, ¶meter, &dataLength, true); if (result == B_OK) break; } if (result != B_OK) { TRACE_ALWAYS("getting inquiry data failed\n"); lun->device_type = B_DISK; lun->removable = true; return result; } TRACE("peripherial_device_type 0x%02x\n", parameter.peripherial_device_type); TRACE("peripherial_qualifier 0x%02x\n", parameter.peripherial_qualifier); TRACE("removable_medium %s\n", parameter.removable_medium ? "yes" : "no"); TRACE("version 0x%02x\n", parameter.version); TRACE("response_data_format 0x%02x\n", parameter.response_data_format); TRACE_ALWAYS("vendor_identification \"%.8s\"\n", parameter.vendor_identification); TRACE_ALWAYS("product_identification \"%.16s\"\n", parameter.product_identification); TRACE_ALWAYS("product_revision_level \"%.4s\"\n", parameter.product_revision_level); lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */ lun->removable = (parameter.removable_medium == 1); return B_OK; }
status_t FTDIDevice::SetControlLineState(uint16 state) { TRACE_FUNCALLS("> FTDIDevice::SetControlLineState(0x%08x, 0x%04x)\n", this, state); int32 control; control = (state & USB_CDC_CONTROL_SIGNAL_STATE_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW; size_t length = 0; status_t status = gUSBModule->send_request(Device(), USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, FTDI_SIO_MODEM_CTRL, control, FTDI_PIT_DEFAULT, 0, NULL, &length); if (status != B_OK) TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status); control = (state & USB_CDC_CONTROL_SIGNAL_STATE_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW; status = gUSBModule->send_request(Device(), USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, FTDI_SIO_MODEM_CTRL, control, FTDI_PIT_DEFAULT, 0, NULL, &length); if (status != B_OK) TRACE_ALWAYS("= FTDIDevice::SetControlLineState(): control set request failed: 0x%08x\n", status); TRACE_FUNCRET("< FTDIDevice::SetControlLineState() returns: 0x%08x\n", status); return status; }
status_t usb_disk_mode_sense(device_lun *lun) { uint32 dataLength = sizeof(scsi_mode_sense_6_parameter); uint8 commandBlock[12]; memset(commandBlock, 0, sizeof(commandBlock)); commandBlock[0] = SCSI_MODE_SENSE_6; commandBlock[1] = lun->logical_unit_number << 5; commandBlock[2] = 0; // Current values commandBlock[7] = dataLength >> 8; commandBlock[8] = dataLength; scsi_mode_sense_6_parameter parameter; status_t result = usb_disk_operation(lun, commandBlock, ¶meter, &dataLength, true); if (result != B_OK) { TRACE_ALWAYS("getting mode sense data failed\n"); return result; } lun->write_protected = (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) != 0; TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no"); return B_OK; }
HIDReport * HIDParser::_FindOrCreateReport(uint8 type, uint8 id) { HIDReport *report = FindReport(type, id); if (report != NULL) return report; report = new(std::nothrow) HIDReport(this, type, id); if (report == NULL) { TRACE_ALWAYS("no memory when allocating report\n"); return NULL; } HIDReport **newReports = (HIDReport **)realloc(fReports, (fReportCount + 1) * sizeof(HIDReport *)); if (newReports == NULL) { TRACE_ALWAYS("no memory when growing report list\n"); delete report; return NULL; } fReports = newReports; fReports[fReportCount++] = report; return report; }
/* 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; (*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; }
status_t BeceemCPU::CPURun() { uint32 clockRegister = 0; // Read current clock register contents if (BizarroReadRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(clockRegister), &clockRegister) != B_OK) { TRACE_ALWAYS("Error: Read of clock reset reg failure\n"); return B_ERROR; } // Adjust clock register contents to start cpu if (fWmxDevice->CPUFlashBoot) clockRegister &= ~(1 << 30); else clockRegister |= (1 << 30); // Write new clock register contents if (BizarroWriteRegister(CLOCK_RESET_CNTRL_REG_1, sizeof(clockRegister), &clockRegister) != B_OK) { TRACE_ALWAYS("Error: Write of clock reset reg failure\n"); return B_ERROR; } return B_OK; }
status_t DavicomDevice::SetupDevice(bool deviceReplugged) { ether_address address; status_t result = ReadMACAddress(&address); if(result != B_OK) { TRACE_ALWAYS("Error reading MAC address:%#010x\n", result); return result; } TRACE("MAC address is:%02x:%02x:%02x:%02x:%02x:%02x\n", address.ebyte[0], address.ebyte[1], address.ebyte[2], address.ebyte[3], address.ebyte[4], address.ebyte[5]); if(deviceReplugged) { // this might be the same device that was replugged - read the MAC address // (which should be at the same index) to make sure if(memcmp(&address, &fMACAddress, sizeof(address)) != 0) { TRACE_ALWAYS("Cannot replace device with MAC address:" "%02x:%02x:%02x:%02x:%02x:%02x\n", fMACAddress.ebyte[0], fMACAddress.ebyte[1], fMACAddress.ebyte[2], fMACAddress.ebyte[3], fMACAddress.ebyte[4], fMACAddress.ebyte[5]); return B_BAD_VALUE; // is not the same } } else fMACAddress = address; return B_OK; }
status_t DavicomDevice::SetPromiscuousMode(bool on) { /* load multicast filter and update promiscious mode bit */ uint8_t rxmode; status_t result = _ReadRegister(RCR, 1, &rxmode); if (result != B_OK) { TRACE_ALWAYS("Error reading RX Control:%#010x\n", result); return result; } rxmode &= ~(RCR_ALL | RCR_PRMSC); if (on) rxmode |= RCR_ALL | RCR_PRMSC; /* else if (ifp->if_flags & IFF_ALLMULTI) rxmode |= RCR_ALL; */ /* write new mode bits */ result = _Write1Register(RCR, rxmode); if(result != B_OK) { TRACE_ALWAYS("Error writing %#04x to RX Control:%#010x\n", rxmode, result); } return result; }
status_t Device::_MultiBufferExchange(multi_buffer_info* Info) { for (int i = 0; i < fStreams.Count(); i++) { if (!fStreams[i]->IsRunning()) { fStreams[i]->Start(); } } TRACE_ALWAYS("Exchange!\n"); snooze(1000000); return B_OK; status_t status = B_ERROR; bool anyBufferProcessed = false; for (int i = 0; i < fStreams.Count() && !anyBufferProcessed; i++) { status = acquire_sem_etc(fBuffersReadySem, 1, B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT, 50000); if (status == B_TIMED_OUT) { TRACE_ALWAYS("Timeout during buffers exchange.\n"); break; } anyBufferProcessed = fStreams[i]->ExchangeBuffer(Info); status = anyBufferProcessed ? B_OK : B_ERROR; } return status; }
status_t usb_printer_transfer_data(printer_device *device, bool directionIn, void *data, size_t dataLength) { status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in : device->bulk_out, data, dataLength, usb_printer_callback, device); if (result != B_OK) { TRACE_ALWAYS("failed to queue data transfer\n"); return result; } do { bigtime_t timeout = directionIn ? READ_TIMEOUT : WRITE_TIMEOUT; result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, timeout); if (result == B_TIMED_OUT) { // Cancel the transfer and collect the sem that should now be // released through the callback on cancel. Handling of device // reset is done in usb_printer_operation() when it detects that // the transfer failed. gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in : device->bulk_out); acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0); } } while (result == B_INTERRUPTED); if (result != B_OK) { TRACE_ALWAYS("acquire_sem failed while waiting for data transfer\n"); return result; } return B_OK; }
status_t AX88178Device::SetupDevice(bool deviceReplugged) { status_t result = ASIXDevice::SetupDevice(deviceReplugged); if (result != B_OK) { return result; } result = fMII.Init(fDevice); if (result != B_OK) { return result; } size_t actualLength = 0; // get the "magic" word from EEPROM result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SROM_ENABLE, 0, 0, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of enabling SROM access:%#010x\n", result); return result; } uint16 eepromData = 0; status_t op_result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_IN, READ_SROM, 0x17, 0, sizeof(eepromData), &eepromData, &actualLength); if (op_result != B_OK) { TRACE_ALWAYS("Error of reading SROM data:%#010x\n", result); } if (actualLength != sizeof(eepromData)) { TRACE_ALWAYS("Mismatch of reading SROM data." "Read %d bytes instead of %d\n", actualLength, sizeof(eepromData)); } result = gUSBModule->send_request(fDevice, USB_REQTYPE_VENDOR | USB_REQTYPE_DEVICE_OUT, WRITE_SROM_DISABLE, 0, 0, 0, 0, &actualLength); if (result != B_OK) { TRACE_ALWAYS("Error of disabling SROM access: %#010x\n", result); return result; } if (op_result != B_OK) { return op_result; } // some shaman's dances with GPIO struct GPIOData { bigtime_t delay; uint16 value; } GPIOCommands[] = {
status_t usb_serial_device_added(usb_device device, void **cookie) { TRACE_FUNCALLS("> usb_serial_device_added(0x%08x, 0x%08x)\n", device, cookie); status_t status = B_OK; const usb_device_descriptor *descriptor = gUSBModule->get_device_descriptor(device); TRACE_ALWAYS("probing device: 0x%04x/0x%04x\n", descriptor->vendor_id, descriptor->product_id); *cookie = NULL; SerialDevice *serialDevice = SerialDevice::MakeDevice(device, descriptor->vendor_id, descriptor->product_id); const usb_configuration_info *configuration; for (int i = 0; i < descriptor->num_configurations; i++) { configuration = gUSBModule->get_nth_configuration(device, i); if (configuration == NULL) continue; status = serialDevice->AddDevice(configuration); if (status == B_OK) { // Found! break; } } if (status < B_OK) { delete serialDevice; return status; } acquire_sem(gDriverLock); for (int32 i = 0; i < DEVICES_COUNT; i++) { if (gSerialDevices[i] != NULL) continue; status = serialDevice->Init(); if (status < B_OK) { delete serialDevice; return status; } gSerialDevices[i] = serialDevice; *cookie = serialDevice; release_sem(gDriverLock); TRACE_ALWAYS("%s (0x%04x/0x%04x) added\n", serialDevice->Description(), descriptor->vendor_id, descriptor->product_id); return B_OK; } release_sem(gDriverLock); return B_ERROR; }
Device::Device(usb_device device) : fStatus(B_ERROR), fOpen(false), fRemoved(false), fInsideNotify(0), fDevice(device), fNonBlocking(false), fAudioControl(this), fControlEndpoint(0), fInStreamEndpoint(0), fOutStreamEndpoint(0), fNotifyReadSem(-1), fNotifyWriteSem(-1), fNotifyBuffer(NULL), fNotifyBufferLength(0), fBuffersReadySem(-1) { const usb_device_descriptor* deviceDescriptor = gUSBModule->get_device_descriptor(device); if (deviceDescriptor == NULL) { TRACE_ALWAYS("Error of getting USB device descriptor.\n"); return; } fVendorID = deviceDescriptor->vendor_id; fProductID = deviceDescriptor->product_id; fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read"); if (fNotifyReadSem < B_OK) { TRACE_ALWAYS("Error of creating read notify semaphore:%#010x\n", fNotifyReadSem); return; } fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write"); if (fNotifyWriteSem < B_OK) { TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n", fNotifyWriteSem); return; } fBuffersReadySem = create_sem(0, DRIVER_NAME "_buffers_ready"); if (fBuffersReadySem < B_OK) { TRACE_ALWAYS("Error of creating ready buffers semaphore:%#010x\n", fBuffersReadySem); return; } if (_SetupEndpoints() != B_OK) { return; } // must be set in derived class constructor fStatus = B_OK; }
status_t usb_disk_inquiry(device_lun *lun) { size_t dataLength = sizeof(scsi_inquiry_6_parameter); uint8 commandBlock[12]; memset(commandBlock, 0, sizeof(commandBlock)); commandBlock[0] = SCSI_INQUIRY_6; commandBlock[1] = lun->logical_unit_number << 5; commandBlock[2] = 0; // page code commandBlock[4] = dataLength; scsi_inquiry_6_parameter parameter; status_t result = B_ERROR; for (uint32 tries = 0; tries < 3; tries++) { result = usb_disk_operation(lun, commandBlock, ¶meter, &dataLength, true); if (result == B_OK) break; } if (result != B_OK) { TRACE_ALWAYS("getting inquiry data failed\n"); lun->device_type = B_DISK; lun->removable = true; return result; } TRACE("peripherial_device_type 0x%02x\n", parameter.peripherial_device_type); TRACE("peripherial_qualifier 0x%02x\n", parameter.peripherial_qualifier); TRACE("removable_medium %s\n", parameter.removable_medium ? "yes" : "no"); TRACE("version 0x%02x\n", parameter.version); TRACE("response_data_format 0x%02x\n", parameter.response_data_format); TRACE_ALWAYS("vendor_identification \"%.8s\"\n", parameter.vendor_identification); TRACE_ALWAYS("product_identification \"%.16s\"\n", parameter.product_identification); TRACE_ALWAYS("product_revision_level \"%.4s\"\n", parameter.product_revision_level); memcpy(lun->vendor_name, parameter.vendor_identification, MIN(sizeof(lun->vendor_name), sizeof(parameter.vendor_identification))); memcpy(lun->product_name, parameter.product_identification, MIN(sizeof(lun->product_name), sizeof(parameter.product_identification))); memcpy(lun->product_revision, parameter.product_revision_level, MIN(sizeof(lun->product_revision), sizeof(parameter.product_revision_level))); lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */ lun->removable = (parameter.removable_medium == 1); return B_OK; }
DavicomDevice::DavicomDevice(usb_device device, const char *description) : fStatus(B_ERROR), fOpen(false), fRemoved(false), fInsideNotify(0), fDevice(device), fDescription(description), fNonBlocking(false), fNotifyEndpoint(0), fReadEndpoint(0), fWriteEndpoint(0), fNotifyReadSem(-1), fNotifyWriteSem(-1), fNotifyBuffer(NULL), fLinkStateChangeSem(-1), fHasConnection(false) { const usb_device_descriptor *deviceDescriptor = gUSBModule->get_device_descriptor(device); if (deviceDescriptor == NULL) { TRACE_ALWAYS("Error of getting USB device descriptor.\n"); return; } fVendorID = deviceDescriptor->vendor_id; fProductID = deviceDescriptor->product_id; fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read"); if (fNotifyReadSem < B_OK) { TRACE_ALWAYS("Error of creating read notify semaphore:%#010x\n", fNotifyReadSem); return; } fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write"); if (fNotifyWriteSem < B_OK) { TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n", fNotifyWriteSem); return; } fNotifyBuffer = (uint8*)malloc(kNotifyBufferSize); if (fNotifyBuffer == NULL) { TRACE_ALWAYS("Error allocating notify buffer\n"); return; } if (_SetupEndpoints() != B_OK) { return; } // TODO : others inits here ? fStatus = B_OK; }
status_t ASIXDevice::Write(const uint8 *buffer, size_t *numBytes) { size_t numBytesToWrite = *numBytes; *numBytes = 0; if (fRemoved) { TRACE_ALWAYS("Error of writing %d bytes to removed device.\n", numBytesToWrite); return B_DEVICE_NOT_FOUND; } TRACE_FLOW("Write %d bytes.\n", numBytesToWrite); TRXHeader header(numBytesToWrite); iovec txData[] = { { &header, sizeof(TRXHeader) }, { (uint8*)buffer, numBytesToWrite } }; size_t startIndex = fUseTRXHeader ? 0 : 1 ; size_t chunkCount = fUseTRXHeader ? 2 : 1 ; status_t result = gUSBModule->queue_bulk_v(fWriteEndpoint, &txData[startIndex], chunkCount, _WriteCallback, this); if (result != B_OK) { TRACE_ALWAYS("Error of queue_bulk_v request:%#010x\n", result); return result; } result = acquire_sem_etc(fNotifyWriteSem, 1, B_CAN_INTERRUPT, 0); if (result < B_OK) { TRACE_ALWAYS("Error of acquiring notify semaphore:%#010x.\n", result); return result; } if (fStatusWrite != B_OK && fStatusWrite != B_CANCELED && !fRemoved) { TRACE_ALWAYS("Device status error:%#010x\n", fStatusWrite); result = gUSBModule->clear_feature(fWriteEndpoint, USB_FEATURE_ENDPOINT_HALT); if (result != B_OK) { TRACE_ALWAYS("Error during clearing of HALT state:%#010x\n", result); return result; } } if (fUseTRXHeader) { *numBytes = fActualLengthWrite - sizeof(TRXHeader); } else { *numBytes = fActualLengthWrite; } TRACE_FLOW("Written %d bytes.\n", *numBytes); return B_OK; }
status_t DavicomDevice::StartDevice() { uint8 registerValue = 0; /* disable loopback */ status_t result = _ReadRegister(NCR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading NCR: %#010x.\n", result); return result; } if (registerValue & NCR_EXT_PHY) TRACE_ALWAYS("Device uses external PHY\n"); registerValue &= ~NCR_LBK; result = _Write1Register(NCR, registerValue); if (result != B_OK) { TRACE_ALWAYS("Error writing %#02X to NCR: %#010x.\n", registerValue, result); return result; } /* Initialize RX control register */ result = _ReadRegister(RCR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading RCR: %#010x.\n", result); return result; } registerValue &= RCR_DIS_LONG & RCR_DIS_CRC & RCR_RXEN; result = _Write1Register(RCR, registerValue); if (result != B_OK) { TRACE_ALWAYS("Error writing %#02X to RCR: %#010x.\n", registerValue, result); return result; } /* clear POWER_DOWN state of internal PHY */ result = _ReadRegister(GPCR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading GPCR: %#010x.\n", result); return result; } registerValue &= GPCR_GEP_CNTL0; result = _Write1Register(GPCR, registerValue); if (result != B_OK) { TRACE_ALWAYS("Error writing %#02X to GPCR: %#010x.\n", registerValue, result); return result; } result = _ReadRegister(GPR, 1, ®isterValue); if (result != B_OK) { TRACE_ALWAYS("Error reading GPR: %#010x.\n", result); return result; } registerValue &= ~GPR_GEP_GEPIO0; result = _Write1Register(GPR, registerValue); if (result != B_OK) { TRACE_ALWAYS("Error writing %#02X to GPR: %#010x.\n", registerValue, result); return result; } return B_OK; }
status_t SerialDevice::_WriteToDevice() { char *buffer = fOutputBuffer; size_t bytesLeft = fOutputBufferSize; status_t status = gTTYModule->tty_read(fDeviceTTYCookie, buffer, &bytesLeft); if (status != B_OK) { TRACE_ALWAYS("write to device: failed to read from TTY: %s\n", strerror(status)); return status; } while (!fDeviceRemoved && bytesLeft > 0) { size_t length = MIN(bytesLeft, fWriteBufferSize); size_t packetLength = length; OnWrite(buffer, &length, &packetLength); status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, packetLength, _WriteCallbackFunction, this); if (status != B_OK) { TRACE_ALWAYS("write to device: queueing failed with status " "0x%08x\n", status); return status; } status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); if (status != B_OK) { TRACE_ALWAYS("write to device: failed to get write done sem " "0x%08x\n", status); return status; } if (fStatusWrite != B_OK) { TRACE("write to device: device status error 0x%08x\n", fStatusWrite); if (fStatusWrite == B_DEV_STALLED) { status = gUSBModule->clear_feature(fWritePipe, USB_FEATURE_ENDPOINT_HALT); if (status != B_OK) { TRACE_ALWAYS("write to device: failed to clear device " "halt\n"); return B_ERROR; } } continue; } buffer += length; bytesLeft -= length; } return B_OK; }
status_t SerialDevice::Write(const char *buffer, size_t *numBytes) { size_t bytesLeft = *numBytes; *numBytes = 0; status_t status = mutex_lock(&fWriteLock); if (status != B_OK) { TRACE_ALWAYS("write: failed to get write lock\n"); return status; } if (fDeviceRemoved) { mutex_unlock(&fWriteLock); return B_DEV_NOT_READY; } while (bytesLeft > 0) { size_t length = MIN(bytesLeft, fWriteBufferSize); size_t packetLength = length; OnWrite(buffer, &length, &packetLength); status = gUSBModule->queue_bulk(fWritePipe, fWriteBuffer, packetLength, WriteCallbackFunction, this); if (status < B_OK) { TRACE_ALWAYS("write: queueing failed with status 0x%08x\n", status); break; } status = acquire_sem_etc(fDoneWrite, 1, B_CAN_INTERRUPT, 0); if (status < B_OK) { TRACE_ALWAYS("write: failed to get write done sem 0x%08x\n", status); break; } if (fStatusWrite != B_OK) { TRACE("write: device status error 0x%08x\n", fStatusWrite); status = gUSBModule->clear_feature(fWritePipe, USB_FEATURE_ENDPOINT_HALT); if (status < B_OK) { TRACE_ALWAYS("write: failed to clear device halt\n"); status = B_ERROR; break; } continue; } buffer += length; *numBytes += length; bytesLeft -= length; } mutex_unlock(&fWriteLock); return status; }
int32 SerialDevice::DeviceThread(void *data) { SerialDevice *device = (SerialDevice *)data; while (!device->fStopDeviceThread) { status_t status = gUSBModule->queue_bulk(device->fReadPipe, device->fReadBuffer, device->fReadBufferSize, device->ReadCallbackFunction, data); if (status < B_OK) { TRACE_ALWAYS("device thread: queueing failed with error: 0x%08x\n", status); break; } status = acquire_sem_etc(device->fDoneRead, 1, B_CAN_INTERRUPT, 0); if (status < B_OK) { TRACE_ALWAYS("device thread: failed to get read done sem 0x%08x\n", status); break; } if (device->fStatusRead != B_OK) { TRACE("device thread: device status error 0x%08x\n", device->fStatusRead); if (gUSBModule->clear_feature(device->fReadPipe, USB_FEATURE_ENDPOINT_HALT) != B_OK) { TRACE_ALWAYS("device thread: failed to clear halt feature\n"); break; } } char *buffer = device->fReadBuffer; size_t readLength = device->fActualLengthRead; device->OnRead(&buffer, &readLength); if (readLength == 0) continue; ddrover *ddr = gTTYModule->ddrstart(NULL); if (!ddr) { TRACE_ALWAYS("device thread: ddrstart problem\n"); return B_NO_MEMORY; } while (device->fInputStopped) snooze(100); gTTYModule->ttyilock(&device->fTTY, ddr, true); for (size_t i = 0; i < readLength; i++) gTTYModule->ttyin(&device->fTTY, ddr, buffer[i]); gTTYModule->ttyilock(&device->fTTY, ddr, false); gTTYModule->ddrdone(ddr); } return B_OK; }
ASIXDevice::ASIXDevice(usb_device device, DeviceInfo& deviceInfo) : fDevice(device), fStatus(B_ERROR), fOpen(false), fRemoved(false), fHasConnection(false), fNonBlocking(false), fInsideNotify(0), fFrameSize(0), fNotifyEndpoint(0), fReadEndpoint(0), fWriteEndpoint(0), fActualLengthRead(0), fActualLengthWrite(0), fStatusRead(B_OK), fStatusWrite(B_OK), fNotifyReadSem(-1), fNotifyWriteSem(-1), fNotifyBuffer(NULL), fNotifyBufferLength(0), fLinkStateChangeSem(-1), fUseTRXHeader(false), fReadNodeIDRequest(kInvalidRequest) { fDeviceInfo = deviceInfo; fIPG[0] = 0x15; fIPG[1] = 0x0c; fIPG[2] = 0x12; memset(&fMACAddress, 0, sizeof(fMACAddress)); fNotifyReadSem = create_sem(0, DRIVER_NAME"_notify_read"); if (fNotifyReadSem < B_OK) { TRACE_ALWAYS("Error of creating read notify semaphore:%#010x\n", fNotifyReadSem); return; } fNotifyWriteSem = create_sem(0, DRIVER_NAME"_notify_write"); if (fNotifyWriteSem < B_OK) { TRACE_ALWAYS("Error of creating write notify semaphore:%#010x\n", fNotifyWriteSem); return; } if (_SetupEndpoints() != B_OK) { return; } // must be set in derived class constructor // fStatus = B_OK; }