// This function MUST BE CALLED BEFORE THE SCHEDULER IS STARTED // It initializes (initialises for you Brits reading this) variables // in the context structure, registers our driver with the // VOS device manager, and creates the thread for handling // requests on the control endpoint. unsigned char usbslaveboms_init(unsigned char vos_dev_num) { vos_driver_t *usbSlaveBoms_cb; slaveBomsCtx = vos_malloc(sizeof(usbSlaveBoms_context)); if (slaveBomsCtx == NULL) return USBSLAVEBOMS_ERROR; //somehow ran out of RAM usbSlaveBoms_cb = vos_malloc(sizeof(vos_driver_t)); if (usbSlaveBoms_cb == NULL) { vos_free(slaveBomsCtx); return USBSLAVEBOMS_ERROR; } // Set up function pointers for our driver usbSlaveBoms_cb->flags = 0; usbSlaveBoms_cb->read = usbSlaveBoms_read; usbSlaveBoms_cb->write = usbSlaveBoms_write; usbSlaveBoms_cb->ioctl = usbSlaveBoms_ioctl; usbSlaveBoms_cb->interrupt = (PF_INT) NULL; usbSlaveBoms_cb->open = (PF_OPEN) NULL; usbSlaveBoms_cb->close = (PF_CLOSE) NULL; // OK - register with device manager vos_dev_init(vos_dev_num, usbSlaveBoms_cb, slaveBomsCtx); // defaults to not connected and no flash drive yet slaveBomsCtx->attached = 0; slaveBomsCtx->flashConnected = 0; // create the thread that handles standard control requests slaveBomsCtx->tcbSetup = vos_create_thread_ex(31, SIZEOF_BOMS_SETUP_MEMORY, usbslaveboms_setup, "BOMSSetup", 2, slaveBomsCtx); // initialize the sempahore to 0 so that anyone waiting for // the device to enum will block vos_init_semaphore(&slaveBomsCtx->enumed, 0); if (slaveBomsCtx->tcbSetup) return USBSLAVEBOMS_OK; return USBSLAVEBOMS_ERROR; }
// This request should never be sent to our device, but since this // is a standard request we will accept it and just do nothing. void set_descriptor_request(usbSlaveBoms_context *ctx, unsigned short wLength) { unsigned char *buffer; usbslave_ioctl_cb_t iocb; usbhost_ioctl_cb_t hc_ioctl; ack_request(ctx); // We read in the info here but throw it away buffer = vos_malloc(wLength); iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SETUP_TRANSFER; iocb.handle = ctx->out_ep0; iocb.request.setup_or_bulk_transfer.buffer = buffer; iocb.request.setup_or_bulk_transfer.size = wLength; vos_dev_ioctl(ctx->handle, &iocb); vos_free(buffer); }
// This function must be called before the scheduler is started. // The function registers our driver with the VOS device manager. unsigned char usbhostBoms_init(unsigned char vos_dev_num) { hostBomsCtx = vos_malloc(sizeof(usbhostBoms_context_t)); memset(hostBomsCtx, 0, sizeof(usbhostBoms_context_t)); // Set up function pointers for our driver usbhostBoms_cb.flags = 0; usbhostBoms_cb.read = usbhostBoms_read; usbhostBoms_cb.write = usbhostBoms_write; usbhostBoms_cb.ioctl = usbhostBoms_ioctl; usbhostBoms_cb.interrupt = (PF_INT) NULL; usbhostBoms_cb.open = usbhostBoms_open; usbhostBoms_cb.close = usbhostBoms_close; // OK - register with device manager vos_dev_init(vos_dev_num, &usbhostBoms_cb, hostBomsCtx); return USBHOSTBOMS_OK; }
// handle requests for a descriptor void get_descriptor_request(usbSlaveBoms_context *ctx) { unsigned char *buffer; // buffer for pass thru to drive usbhost_ioctl_cb_t hc_ioctl; usbslave_ioctl_cb_t iocb; usb_deviceRequest_t *devReq; unsigned char hValue; // high byte of the descriptor requested unsigned char lValue; // low byte of the descriptor requested unsigned short wLength; unsigned short siz; uint32 ul_siz; unsigned char *src; unsigned char cond; tmr_ioctl_cb_t tmr_iocb; devReq = (usb_deviceRequest_t *) ctx->setup_buffer; hValue = devReq->wValue >> 8; // shift away the low byte lValue = devReq->wValue & 0xff; // and away the high byte wLength = devReq->wLength; switch (hValue) // the high byte determines type of descriptor requested { case USB_DESCRIPTOR_TYPE_DEVICE: ul_siz = (uint32) wLength; iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SETUP_TRANSFER; iocb.handle = ctx->in_ep0; // update the device descriptor VID/PID from our list vos_lock_mutex(&vidPidMutex); device_descriptor[8] = vidPid[currentVidPidIndex] & 0xff; device_descriptor[9] = vidPid[currentVidPidIndex] >> 8; device_descriptor[10] = vidPid[currentVidPidIndex+1] & 0xff; device_descriptor[11] = vidPid[currentVidPidIndex+1] >> 8; vos_unlock_mutex(&vidPidMutex); //updated LCD update_lcd_vidpid(); iocb.request.setup_or_bulk_transfer.buffer = device_descriptor; iocb.request.setup_or_bulk_transfer.size = (int16) ul_siz; vos_dev_ioctl(ctx->handle, &iocb); // start this timer and if it is not killed then the next VID/PID will be selected // this is done to detect an unsuccessful enumeration which is assumed // to result from endpoint security blocking if (autoMode) { tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_START; vos_dev_ioctl(hTimer, &tmr_iocb); } return; break; case USB_DESCRIPTOR_TYPE_CONFIGURATION: // host will initially ask for first 9 bytes of configuration descriptor // this descriptor header has the size of the full descriptor which // is actually a composite of the configuration/interface/endpoints. // Once host knows the complete descriptor size it makes a second // request for the whole thing siz = wLength == 9?9:sizeof(config_descriptor); ul_siz = (uint32) siz; iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SETUP_TRANSFER; iocb.handle = ctx->in_ep0; iocb.request.setup_or_bulk_transfer.buffer = config_descriptor; iocb.request.setup_or_bulk_transfer.size = (int16) ul_siz; vos_dev_ioctl(ctx->handle, &iocb); // stop the timer because we are being asked to enumerate if(autoMode) { tmr_iocb.ioctl_code = VOS_IOCTL_TIMER_STOP; vos_dev_ioctl(hTimer, &tmr_iocb); } return; case USB_DESCRIPTOR_TYPE_STRING: if (lValue == 0) // language type { src = str0_descriptor; siz = sizeof(str0_descriptor); } else if (lValue == 1) // manufacturer { src = str1_descriptor; siz = sizeof(str1_descriptor); } else if (lValue == 2) // product { src = str2_descriptor; siz = sizeof(str2_descriptor); } else if (lValue == 3) // serial number { src = str3_descriptor; siz = sizeof(str3_descriptor); } cond = (unsigned char) (wLength != siz); if (siz > wLength) // don't return more than was asked for siz = wLength; ul_siz = (uint32) siz; iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SETUP_TRANSFER; iocb.handle = ctx->in_ep0; iocb.request.setup_or_bulk_transfer.buffer = src; iocb.request.setup_or_bulk_transfer.size = (int16) ul_siz; vos_dev_ioctl(ctx->handle, &iocb); return; default: // if drive is connected get descriptor from it if (ctx->flashConnected) { buffer = vos_malloc(wLength); hc_ioctl.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER; hc_ioctl.handle.ep = hostBomsCtx->epCtrl; hc_ioctl.set = &(ctx->setup_buffer[0]); hc_ioctl.get = buffer; // descriptor from drive vos_dev_ioctl(hostBomsCtx->hc, &hc_ioctl); iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SETUP_TRANSFER; iocb.handle = ctx->in_ep0; iocb.request.setup_or_bulk_transfer.buffer = buffer; iocb.request.setup_or_bulk_transfer.size = wLength; vos_dev_ioctl(ctx->handle, &iocb); vos_free(buffer); } else { // respond with Request Error set_control_ep_halt(ctx); } } }
BOOL DisplayDescriptors(BYTE ThreadID, usbhost_device_handle* ifDev) { BYTE* ConfigurationDescriptorPtr; usb_deviceRequest_t DeviceRequest; usb_deviceDescriptor_t DeviceDescriptor; usb_deviceConfigurationDescriptor_t ConfigurationDescriptorHeader; usb_deviceInterfaceDescriptor_t* InterfaceDescriptorPtr; usbhost_ioctl_cb_t hc_iocb; usbhost_ep_handle* EP0; BYTE Status; BYTE* DescriptorPtr; // Get a handle for EP0 hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_CONTROL_ENDPOINT_HANDLE; hc_iocb.handle.dif = ifDev; hc_iocb.get = &EP0; Status = i_vos_dev_ioctl(ThreadID, hDevice[Host], &hc_iocb); if (Status != USBHOST_OK) return dprint("\nCould not attach to Control Endpoint, status = %d", &Status); // Read the Device Descriptor hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER; hc_iocb.handle.ep = EP0; DeviceRequest.bmRequestType = USB_BMREQUESTTYPE_DEV_TO_HOST; DeviceRequest.bRequest = USB_REQUEST_CODE_GET_DESCRIPTOR; DeviceRequest.wValue = USB_DESCRIPTOR_TYPE_DEVICE<<8; DeviceRequest.wIndex = 0; DeviceRequest.wLength = sizeof(DeviceDescriptor); hc_iocb.set = &DeviceRequest; hc_iocb.get = &DeviceDescriptor; Status = i_vos_dev_ioctl(ThreadID, hDevice[Host], &hc_iocb); if (Status != USBHOST_OK) return dprint("\nCould not read Device Descriptor, status = %d", &Status); // Display the Device Descriptor dprint("\nDevice Descriptor is:", 0); dprintBuffer((BYTE*)&DeviceDescriptor, sizeof(DeviceDescriptor)); // Read the Configuration Descriptor header // Note that lines marked /// are not needed but I left them in as comments so that you can better see what is going on /// hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER; /// hc_iocb.handle.ep = EP0; /// DeviceRequest.bmRequestType = USB_BMREQUESTTYPE_DEV_TO_HOST; /// DeviceRequest.bRequest = USB_REQUEST_CODE_GET_DESCRIPTOR; DeviceRequest.wValue = USB_DESCRIPTOR_TYPE_CONFIGURATION<<8; /// DeviceRequest.wIndex = 0; DeviceRequest.wLength = sizeof(ConfigurationDescriptorHeader); /// hc_iocb.set = &DeviceRequest; hc_iocb.get = &ConfigurationDescriptorHeader; Status = i_vos_dev_ioctl(ThreadID, hDevice[Host], &hc_iocb); if (Status != USBHOST_OK) return dprint("\nCould not read Configuration Descriptor Header, status = %d", &Status); // Get some memory for the Configuration Descriptor ConfigurationDescriptorPtr = vos_malloc(ConfigurationDescriptorHeader.wTotalLength); if (ConfigurationDescriptorPtr == 0) return dprint("\nmalloc failed, no free memory", 0); // Read the whole Configuration Descriptor /// hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER; /// hc_iocb.handle.ep = EP0; /// DeviceRequest.bmRequestType = USB_BMREQUESTTYPE_DEV_TO_HOST; /// DeviceRequest.bRequest = USB_REQUEST_CODE_GET_DESCRIPTOR; /// DeviceRequest.wValue = USB_DESCRIPTOR_TYPE_CONFIGURATION<<8; /// DeviceRequest.wIndex = 0; DeviceRequest.wLength = ConfigurationDescriptorHeader.wTotalLength; /// hc_iocb.set = &DeviceRequest; hc_iocb.get = ConfigurationDescriptorPtr; Status = i_vos_dev_ioctl(ThreadID, hDevice[Host], &hc_iocb); if (Status != USBHOST_OK) return dprint("\nCould not read Configuration Descriptor, status = %d", &Status); // Display the Configuration Descriptor dprint("\nConfiguration Descriptor is:", 0); DescriptorPtr = ConfigurationDescriptorPtr; while (DescriptorPtr<(ConfigurationDescriptorPtr+ConfigurationDescriptorHeader.wTotalLength)) { dprintBuffer(DescriptorPtr, *DescriptorPtr); DecodeDescriptor(DescriptorPtr); DescriptorPtr += *DescriptorPtr; } InterfaceDescriptorPtr = ConfigurationDescriptorPtr+9; if (InterfaceDescriptorPtr->bInterfaceClass == 3) { dprint("\nThis is a HID ", 0); if (InterfaceDescriptorPtr->bInterfaceProtocol == 1) dprint("Keyboard", 0); if (InterfaceDescriptorPtr->bInterfaceProtocol == 2) dprint("Mouse", 0); } if (InterfaceDescriptorPtr->bInterfaceClass == 9) dprint("\nThis is a HUB ", 0); vos_free(ConfigurationDescriptorPtr); }