int WANDongleSerialPort::writePacket() { tx_mtx.lock(); if(lock_tx) { USB_ERR("Fail"); tx_mtx.unlock(); return -1; } if( bulk_out == NULL ) { USB_WARN("Port is disconnected"); tx_mtx.unlock(); return -1; } lock_tx = true; //Transmitting tx_mtx.unlock(); // USB_DBG("writePacket"); //lock_tx.lock(); USB_TYPE res = host->bulkWrite(dev, (USBEndpoint *)bulk_out, buf_out, buf_out_len, false); //Queue transfer if(res != USB_TYPE_PROCESSING) { //lock_tx.unlock(); USB_ERR("host->bulkWrite() returned %d", res); ThisThread::sleep_for(100); return -1; } return 0; }
int WANDongleSerialPort::readPacket() { USB_DBG("Read packet on %p", this); rx_mtx.lock(); if(lock_rx) { USB_ERR("Fail"); rx_mtx.unlock(); return -1; } if( bulk_in == NULL ) { USB_WARN("Port is disconnected"); rx_mtx.unlock(); return -1; } lock_rx = true; //Receiving rx_mtx.unlock(); // USB_DBG("readPacket"); //lock_rx.lock(); USB_TYPE res = host->bulkRead(dev, (USBEndpoint *)bulk_in, buf_in, ((USBEndpoint *)bulk_in)->getSize(), false); //Queue transfer if(res != USB_TYPE_PROCESSING) { //lock_rx.unlock(); USB_ERR("host->bulkRead() returned %d", res); ThisThread::sleep_for(100); return -1; } return 0; }
static int usb_presence_rx(struct req_ctx *rctx) { struct openpcd_hdr *poh = (struct openpcd_hdr *) rctx->data; switch (poh->cmd) { case OPENPCD_CMD_PRESENCE_UID_GET: DEBUGPCRF("get presence UID"); poh->flags |= OPENPCD_FLAG_RESPOND; if(last_polled_uid) { rctx->tot_len += 4; poh->data[0]=(u_int8_t)(last_polled_uid>>24); poh->data[1]=(u_int8_t)(last_polled_uid>>16); poh->data[2]=(u_int8_t)(last_polled_uid>> 8); poh->data[3]=(u_int8_t)(last_polled_uid ); last_polled_uid=0; } break; default: DEBUGP("UNKNOWN "); return USB_ERR(USB_ERR_CMD_UNKNOWN); break; } if (poh->flags & OPENPCD_FLAG_RESPOND) return USB_RET_RESPOND; return 0; }
void USBHostHub::portReset(uint8_t port) { // reset port uint32_t status; USB_DBG("reset port %d on hub: %p [this: %p]", port, dev, this) setPortFeature(PORT_RESET_FEATURE, port); while(1) { status = getPortStatus(port); if (status & (PORT_ENABLE | PORT_RESET)) break; if (status & PORT_OVER_CURRENT) { USB_ERR("OVER CURRENT DETECTED\r\n"); clearPortFeature(PORT_OVER_CURRENT, port); host->deviceDisconnected(dev->getHub() + 1, port, this, 0); break; } Thread::wait(10); } }
int WANDongleSerialPort::putc(int c) { tx_mtx.lock(); if(!lock_tx) { if(buf_out_len < max_out_size) { buf_out[buf_out_len] = (uint8_t)c; buf_out_len++; } } else { USB_ERR("CAN'T WRITE!"); } tx_mtx.unlock(); return c; }
int WANDongleSerialPort::getc() { rx_mtx.lock(); int c = 0; if(!lock_rx) { if(buf_in_read_pos < buf_in_len) { c = (int)buf_in[buf_in_read_pos]; buf_in_read_pos++; } } else { USB_ERR("CAN'T READ!"); } rx_mtx.unlock(); return c; }
static struct platform_device * tegra_usb_otg_host_register(struct platform_device *ehci_device, struct tegra_ehci_platform_data *pdata) { struct platform_device *pdev; void *platform_data; int val; pdev = platform_device_alloc(ehci_device->name, ehci_device->id); if (!pdev) return NULL; val = platform_device_add_resources(pdev, ehci_device->resource, ehci_device->num_resources); if (val) goto error; pdev->dev.dma_mask = ehci_device->dev.dma_mask; pdev->dev.coherent_dma_mask = ehci_device->dev.coherent_dma_mask; platform_data = kmalloc(sizeof(struct tegra_ehci_platform_data), GFP_KERNEL); if (!platform_data) goto error; memcpy(platform_data, pdata, sizeof(struct tegra_ehci_platform_data)); pdev->dev.platform_data = platform_data; val = platform_device_add(pdev); if (val) goto error_add; return pdev; error_add: kfree(platform_data); error: USB_ERR("%s: failed to add the host controller device\n", __func__); platform_device_put(pdev); return NULL; }
void USBHostHub::rxHandler() { uint32_t status; if (int_in) { if (int_in->getState() == USB_TYPE_IDLE) { for (int port = 1; port <= nb_port; port++) { status = getPortStatus(port); USB_DBG("[hub handler hub: %d] status port %d [hub: %p]: 0x%X", dev->getHub(), port, dev, status); // if connection status has changed if (status & C_PORT_CONNECTION) { if (status & PORT_CONNECTION) { USB_DBG("[hub handler hub: %d - port: %d] new device connected", dev->getHub(), port); host->deviceConnected(dev->getHub() + 1, port, status & PORT_LOW_SPEED, this); } else { USB_DBG("[hub handler hub: %d - port: %d] device disconnected", dev->getHub(), port); host->deviceDisconnected(dev->getHub() + 1, port, this, 0); } clearPortFeature(C_PORT_CONNECTION_FEATURE, port); } if (status & C_PORT_RESET) { clearPortFeature(C_PORT_RESET_FEATURE, port); } if (status & C_PORT_ENABLE) { clearPortFeature(C_PORT_ENABLE_FEATURE, port); } if ((status & PORT_OVER_CURRENT)) { USB_ERR("OVER CURRENT DETECTED\r\n"); clearPortFeature(PORT_OVER_CURRENT, port); host->deviceDisconnected(dev->getHub() + 1, port, this, 0); } } } host->interruptRead(dev, int_in, buf, 1, false); } }
bool WANDongle::tryConnect() { //FIXME should run on USB thread USB_DBG("Trying to connect device"); if (dev_connected) { USB_DBG("Device is already connected!"); return true; } m_pInitializer = NULL; //Protect from concurrent access from USB thread USBHost::Lock lock(host); for (int i = 0; i < MAX_DEVICE_CONNECTED; i++) { if ((dev = host->getDevice(i)) != NULL) { m_pInitializer = NULL; //Will be set in setVidPid callback USB_DBG("Enumerate"); int ret = host->enumerate(dev, this); if(ret) { return false; } USB_DBG("Device has VID:%04x PID:%04x", dev->getVid(), dev->getPid()); if(m_pInitializer) { //If an initializer has been found //USB_DBG("m_pInitializer=%p", m_pInitializer); //USB_DBG("m_pInitializer->getSerialVid()=%04x", m_pInitializer->getSerialVid()); //USB_DBG("m_pInitializer->getSerialPid()=%04x", m_pInitializer->getSerialPid()); if ((dev->getVid() == m_pInitializer->getSerialVid()) && (dev->getPid() == m_pInitializer->getSerialPid())) { USB_DBG("The dongle is in virtual serial mode"); host->registerDriver(dev, 0, this, &WANDongle::init); m_serialCount = m_pInitializer->getSerialPortCount(); if( m_serialCount > WANDONGLE_MAX_SERIAL_PORTS ) { m_serialCount = WANDONGLE_MAX_SERIAL_PORTS; } USB_DBG("Initied Serial Ports %d",m_serialCount); for(int j = 0; j < m_serialCount; j++) { USB_DBG("Connecting serial port #%d", j+1); USB_DBG("Ep %p", m_pInitializer->getEp(dev, j, false)); USB_DBG("Ep %p", m_pInitializer->getEp(dev, j, true)); m_serial[j].connect( dev, m_pInitializer->getEp(dev, j, false), m_pInitializer->getEp(dev, j, true) ); } USB_DBG("Device connected"); dev_connected = true; return true; } else if ((dev->getVid() == m_pInitializer->getMSDVid()) && (dev->getPid() == m_pInitializer->getMSDPid())) { USB_DBG("Dongle detected in Wrong USB mode"); //Try to switch if( m_pInitializer->switchMode(dev) ) { USB_DBG("Switched OK"); return false; //Will be connected on a next iteration } else { USB_ERR("Could not switch mode"); return false; } } } //if() } //if() } //for() return false; }
/* * This function will be called after a whole SETUP-OUT-IN transfer. */ void do_vendor_out_complete( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl) { int value = 0; u16 w_index = ctrl->wIndex; u16 w_value = ctrl->wValue; u16 w_length = ctrl->wLength; void (*fp)(void); char * buf; //USB_DBG("do_vendor_out_complete()\n"); switch (ctrl->bRequest) { case AM_REQ_WRITE_MEM: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; USB_DBG("--am req write memory completed\n\n"); break; case AM_REQ_FILL_MEM: buf = _pcd->buf; unsigned int addr,i; for(i = 0; i < _pcd->length; i+=8){ addr = *((unsigned int *)&buf[i]) ; value = *((unsigned int *)&buf[i+4]) ; *(unsigned int*)addr = value; } break; case AM_REQ_WRITE_AUX: buf = _pcd->buf; unsigned int data =0; data = *((unsigned int *)&buf[0]) ; //reg value value = (w_value << 16) + w_index; //aux reg //_sr(data,value); break; case AM_REQ_MODIFY_MEM: do_modify_memory(w_value,_pcd->buf); break; case AM_REQ_RUN_IN_ADDR: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; value = (w_value << 16) + w_index; USB_DBG("run addr = 0x%08X\n",value); fp = (void(*)(void))value; dwc_otg_power_off_phy(); fp(); break; case AM_REQ_WR_LARGE_MEM: value = 1; // is_out = 1 case AM_REQ_RD_LARGE_MEM: _pcd->bulk_out = value; // read or write _pcd->bulk_buf = (char *)(*(unsigned int*)buff); // board address _pcd->bulk_data_len = (*(unsigned int*) &buff[4]); // data length start_bulk_transfer(_pcd); break; default: USB_ERR("--unknown vendor req comp %02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } w_length = 0;//remove compile warning return; }
/** * This functions delegates vendor ctrl request. */ void do_vendor_request( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl) { int value =0; u16 w_index = ctrl->wIndex; u16 w_value = ctrl->wValue; u16 w_length = ctrl->wLength; switch (ctrl->bRequest) { case AM_REQ_WRITE_MEM: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; USB_DBG("--am req write memory\n"); value = (w_value << 16) + w_index; USB_DBG("addr = 0x%08X, size = %d\n\n",value,w_length); _pcd->buf = (char *)value; // copy to dst memory directly _pcd->length = w_length; break; case AM_REQ_READ_MEM: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; value = (w_value << 16) + w_index; usb_memcpy((char *)buff,(char*)value,w_length); _pcd->buf = buff; _pcd->length = w_length; break; case AM_REQ_READ_AUX: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; unsigned int data = 0; value = (w_value << 16) + w_index; //data = _lr(value); *(unsigned int *)buff = data; _pcd->buf = buff; _pcd->length = w_length; break; case AM_REQ_FILL_MEM: case AM_REQ_WRITE_AUX: case AM_REQ_MODIFY_MEM: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; _pcd->buf = buff; _pcd->length = w_length; break; case AM_REQ_RUN_IN_ADDR: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE)) break; value = (w_value << 16) + w_index; USB_DBG("--am req run in addr %p\n\n",value); _pcd->buf = buff; _pcd->length = w_length; break; case AM_REQ_WR_LARGE_MEM: value = 1; case AM_REQ_RD_LARGE_MEM: USB_DBG("--am req large %s mem \n\n",value?"write":"read"); _pcd->bulk_len = w_value; // block length _pcd->bulk_num = w_index; // number of block _pcd->buf = buff; _pcd->length = w_length; break; case AM_REQ_IDENTIFY_HOST: buff[0] = USB_ROM_VER_MAJOR; buff[1] = USB_ROM_VER_MINOR; buff[2] = USB_ROM_STAGE_MAJOR; buff[3] = USB_ROM_STAGE_MINOR; _pcd->buf = buff; _pcd->length = w_length; need_check_timeout = 0; break; default: USB_ERR("--unknown vendor req %02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); break; } return; }
/** * This functions delegates the setup command to the gadget driver. */ void do_gadget_setup( pcd_struct_t *_pcd, struct usb_ctrlrequest * ctrl) { int value; u16 w_index = ctrl->wIndex; u16 w_value = ctrl->wValue; u16 w_length = ctrl->wLength; /* usually this just stores reply data in the pre-allocated ep0 buffer, * but config change events will also reconfigure hardware. */ switch (ctrl->bRequest) { case USB_REQ_GET_DESCRIPTOR: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; //time_out_val = USB_ROM_DRIVER_TIMEOUT;// Wait SetConfig (PC install driver OK) need_check_timeout = 0; switch (w_value >> 8) { case USB_DT_DEVICE: USB_DBG("--get device descriptor\n\n"); value = min(w_length, (u16) sizeof device_desc); usb_memcpy(buff, (char*)&device_desc, value); _pcd->buf = buff; _pcd->length = value; break; case USB_DT_DEVICE_QUALIFIER: USB_DBG("--get device qualifier\n\n"); break; case USB_DT_OTHER_SPEED_CONFIG: DBG("--get other speed configuration descriptor\n"); DBG("--other speed configuration descriptor length :%d\n", value); break; case USB_DT_CONFIG: USB_DBG("--get configuration descriptor: size %d\n",w_length); if(w_length > USB_DT_CONFIG_SIZE) { value = TOTAL_CONFIG_DESC_LEN; usb_memcpy(buff+USB_DT_CONFIG_SIZE,(void*)&intf_desc[0],INTF_CONFIG_DESC_LEN); } else value = w_length; usb_memcpy(buff, (void*)&config_desc, USB_DT_CONFIG_SIZE); _pcd->buf = buff; _pcd->length = value; USB_DBG("--configuration descriptor length :%d\n\n", value); break; case USB_DT_STRING: USB_DBG("--get string descriptor: id: %d\n",w_value & 0xff); switch(w_value & 0xff){ case 0: // IDs usb_memcpy(buff,(void*)dt_string_id,DT_STRING_ID_LEN); break; case 1: // STRING_MANUFACTURER usb_memcpy(buff,(void*)dt_string_vid,DT_STRING_VID_LEN); break; case 2://STRING_PRODUCT usb_memcpy(buff,(void*)dt_string_pid,DT_STRING_PID_LEN); break; case 3://STRING_SERIAL usb_memcpy(buff,(void*)dt_string_serial,DT_STRING_SERIAL_LEN); break; default: USB_ERR("Error string id!\n"); buff[0] = 0; break; } _pcd->buf = buff; _pcd->length = buff[0]; USB_DBG("--get string descriptor: return length: %d\n\n",_pcd->length); break; } break; case USB_REQ_SET_CONFIGURATION: if (ctrl->bRequestType != (USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; USB_DBG("--set configuration\n\n"); _pcd->buf = 0; _pcd->length = 0; _pcd->request_config = 1; /* Configuration changed */ //need_check_timeout = 0; break; case USB_REQ_GET_CONFIGURATION: if (ctrl->bRequestType != (USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE)) break; USB_DBG("--get configuration\n\n"); buff[0] = 1; _pcd->buf = buff; _pcd->length = 1; break; default: USB_ERR("--unknown control req %02x.%02x v%04x i%04x l%u\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); } w_index = 0; //remove compile warning return ; }