Unison Help
![](https://rowebots.com/wp-content/plugins/documentor/skins/default/images/search.png)
- Unison Kernel
- Pthreads
- pthread_create()
- pthread_exit()
- pthread_self()
- pthread_equal()
- pthread_join()
- pthread_detach()
- pthread_setschedparam()
- pthread_getschedparam()
- pthread_attr_init()
- pthread_attr_destroy()
- pthread_attr_setstackaddr()
- pthread_attr_getstackaddr()
- pthread_attr_setstacksize()
- pthread_attr_getstacksize()
- pthread_attr_setschedparam()
- pthread_attr_getschedparam()
- pthread_attr_setdetachstate()
- pthread_attr_getdetachstate()
- pthread_stackinfo()
- pthread_setprio()
- pthread_getprio()
- sched_get_priority_max()
- sched_get_priority_min()
- sched_yield()
- Pthread Cancellation
- Mutex
- Semaphores
- Message Queues
- Conditional Variables
- Barriers
- Timers
- Clocks
- Memory Allocation
- Rendezvous
- Interrupts
- Directory Services
- Miscellaneous
- Pthreads
- Unison I/O Library
- Unison STDIO Library
- STDIO Library Calls
- clearerr()
- dprintf()
- fclose()
- fdopen()
- feof()
- ferror()
- fileno()
- fflush()
- fgetc()
- fgetpos()
- fgets()
- fopen()
- fprintf()
- fputc()
- fputs()
- fread()
- freopen()
- fscanf()
- fseek()
- fseeko()
- fsetpos()
- ftell()
- ftello()
- fwrite()
- getc()
- getc_unlocked()
- getchar()
- getchar_unlocked()
- getdelim()
- getline()
- gets()
- get_stderr_ptr()
- get_stdin_ptr()
- get_stdout_ptr()
- noperprintf()
- perprintf()
- perror()
- posix_compat()
- printf()
- putc()
- putc_unlocked()
- putchar()
- putchar_unlocked()
- puts()
- remove()
- rewind()
- scanf()
- setbuf()
- setvbuf()
- snprintf()
- sprintf()
- sscanf()
- stderr_init()
- stderr_close()
- stdin_init()
- stdin_close()
- stdout_init()
- stdout_close()
- vdprintf()
- vscanf()
- vsscanf()
- vfscanf()
- vprintf()
- vsnprintf()
- vsprintf()
- vfprintf()
- ungetc()
- Do-nothing Stubs
- STDIO Library Calls
- Unison LIBC Library
- Unison I/O Servers
- Graphics, Camera, Video, Audio
- Network Protocols
- TCP and UDP Server - tcpd
- DHCP Client Service - dhcp client
- DHCP Server - dhcpd
- Telnet Server - telnetd
- Tiny FTP Server - tftpd
- Point to Point - pppd
- Network Translation - NAT with PAT
- Firewall
- Tiny HTTP Server - thttpd
- Tiny HTTP Server with TLS
- POP3 Server
- Simple Mail Transfer Protocol Services (SMTP)
- Bootp Protocol
- File Transfer Protocol Server (FTP)
- File Transfer Client Services
- RPC / XDR
- DNS Client
- HTTP/HTTPS Client
- REST Client
- AutoIP Service - autoip client
- mDNS server - mdnsd
- SNTP Client
- SNMP Agent - Snmpd server
- SSL/TLS library
- SSH server
- IP security
- Power Control
- Serial I/O
- System Services
- Universal Serial Bus (USB)
- Wireless
- Remedy Tools for Unison
7.30.3.USB Embedded Host Server #
NAME
USB Embedded Host Server – usbh
SYNOPSIS
#include <sys.h>
#include <stdio.h>
#include <usb.h>
Additional parametrs for start USB HOST :
usb_list_param.host_param = NULL;
DESCRIPTION
The Unison USB Host is multi layer high performance USB Embedded stack.It part of USB server solution. USB Host support Control, Bulk, Interrupt and Isochronous transfers according USB 1.1 and USB 2.0 specifications. USB HOST stack has a multi-layered structure comprised of a Hardware Layer, a USB Core Layer and USB Class driver Layer.
Key Features:
· USB 1.1 and 2.0 compliant,
· Supports Low-speed (1.5 Mb/s), Full-speed (12Mb/s), and High-speed (480 Mb/s),
· Contains an integrated root hub and a port manager,
· Provides a HUB Class Driver supporting Low-speed, Full-speed, and High-speed,
· Easy hi-speed end usage.
USB Host component structure example:
Hardware Layer
Unison’s USB Hardware Layer is designed to be an easy adaptation to support any USB host controller. It complies with the USB v1.1 and USB v2.0 specifications. It supports Control, Bulk, Interrupt, and Isochronous transfer modes at low, full, and high speeds. The required USB management and extended error recovery mechanisms for reliable operation are implemented internally. The hardware layer can be implemented to run with USB interrupts or without it (with respect to the specific USB hardware).
Host Core Layer
Through the core, the stack manages multiple devices and hubs simultaneously and fully supports hot-swapping of various devices and hubs. The Host Core Layer supports dynamic device enumeration and identification. It provides application access to the necessary USB Device Class Driver and hardware layer.
Class Driver Layer
The Class Driver Layer implements the necessary functions for a USB class definition. Such classes include mass storage (USB MSC Flash stick, USB MSC HDD etc.), serial communications (USB CDC-serial), and human interface. This layer controls the connected devices and provides functionality to higher level services (i.e. R/W control for various file systems such as the Fat-fs).
Hub Class Driver
The Unison Host stack implementation contains a root hub and port manager supporting the connection of one or more external USB hubs to the host system. This host implementation will support low, full, and high speed devices connected through a high speed hub.
MSC class Device Driver
The USB Mass Storage (device) Class is a class implementation for Unison’s USB Host Core Layer. It extends the embedded USB Host Core Layer with an implementation of the USB Mass Storage protocol. The MSC can support SCSI, SFF-8070i, RBC and other storage protocols. The MSC device class maps read/write requests issued by a file system implementation (such as FatFS) to protocol-specific commands. It also manages initialization, discovery and error recovery. The Mass Storage Class implementation uses only the control channel endpoint with two bulk endpoints.
CDC Class Device Driver
The USB Class Definition (for serial) Communications implementation is a class driver for Unison’s Host Core Layer. It allows an application to access a physical CDC device. The CDC implementation supports: Universal Serial Bus Device Class (www.usb.org/developers/defined_class), CP2101, and other devices. Any USB serial port represented within system as a TTY port.
Usb Serve can support other Classes by simply add new classes libraries
After start, USB host can execute callback function and sent to it some events:
_USBH_CON_EVT //USB HOST detect connected device to its port _USBH_DISCON_EVT //USB HOST detect disconnect device from its port _USBH_PWR_EVT //USB HOST detect power failure _USBH_VBUS_EVT //USB HOST detect vbus error event (overcurrent) _USB_ROLE_HOST_EVT //role changed to host
USB Events and their dependent parameter:
_USBH_CON_EVT – a new device is connected. This event happens when new device is recognized – “param” is a pointer to structure which holds the device information within the type (tUSB_dev_info *).
_USBH_DISCON_EVT – a device disconnected. This event happens when device is disconnected – “param” is a pointer to structure holding the disconnected device information held by the type (tUSB_dev_info *).
_USBH_PWR_EVT – Power failure (overcurrent). For this event, “param” is null.
_USBH_VBUS_EVT – Power feeding error (feeding voltage is more then admissible). For this event, “param” is null.
_USB_ROLE_HOST_EVT – USB role has been changed. Now role IS USB Host.
Using the usb_event callback:
void USBH_event(tUSB_event evt, void *param) { tUSB_dev_info * dev_info = (tUSB_dev_info *)param; xprintf("USBH_event\n"); switch (evt) { case _USBH_CON_EVT: { //we have usb device connected printf("---- USB device connected:\n"); xprintf("\tClass %x Subclass %x\n", dev_info->Class, de...v_info->Subclass); xprintf("\tproductID %x VendorID %x\n",dev_info->pdouctID , dev_info->VendorID); xprintf("\tRevision %x \n", dev_info->Rev); switch (dev_info->Speed) { case 0: xprintf("LOW SPEED device\n"); break; case 1: xprintf("FULL SPEED device\n"); break; case 2: xprintf("HIGH SPEED device\n"); break; } break; case _USBH_DISCON_EVT: //we have usb device disconnected xprintf("USB device was disconnected. Class %x\n", dev_info->Class); break; case _USBH_PWR_EVT: xprintf("USB power event!\n"); break; case _USBH_VBUS_EVT: xprintf("USB vbus event!\n"); break; case _USB_ROLE_HOST_EVT: xprintf("Change role to HOST\n"); break; } }
The USB host implementation provides the following operations:
int usbh_get_dev_cnt (void);
Returns total count of connected devices (including root hub).
int usbh_get_info(char devnum, tUSB_dev_info * info);
Return information in dev_info structure about a connected device, with devnum device number.
Returns -1, if the operation fails.
int usbh_get_info_ex(int devaddr, int Bus, tUSB_dev_info * info);
Return information in dev_info structure about a connected device, connected to port Bus and with USB address devaddr, to the structure pointed to by dev_info.
Returns -1, if the operation fails.
usbh_mount (tUSB_dev_info * dev_info, void *usb_driver);
Initializes the connected device described by the structure pointed to by dev_info and return the driver functions for top level application in the structure pointed to by usb_driver. The type of the structure pointed to by usb_driver is dependent on the mounted device type.
For example: for a MSC device *usb_driver is pointer to the driver functions for a FatFs file system.
Returns -1, if the operation fails.
usbh_umount (int dev_n);
Deallocate the resources allocated by usbh_mount for the device number dev_n.
Returns -1, if operation fails.
An example illustrating the initialization and mount of a USB MSC:
{ DISK_DRIVER usb_driver; tUSB_dev_info dev_info; int dev_cnt; int DEVNO; dev_cnt = usbh_get_dev_cnt(); //get all connected device count xprintf("Now %d USB devices connected", dev_cnt); usb_get_info(1, &dev_info); // getting info about first connected device if (dev_info.Class == USB_CLASS_MASS_STORAGE) { usbh_mount(&dev_info, &usb_driver); //get MSC driver functions for (FatFs) read, write etc... fatfs_add_drv(FSYS_MSC_MOUNT, &usb_driver, &DEVNO); //add new disk driver to FatFs //return DEVNO - local disk driver number ... ... ... usbh_umount(usbd_info.Dev_n); }
The typical operation for a usbh server involves several steps.
· Create a usbh server, so that commands can be carried out for the selected media. Use pthread_create to do this.
· Register the usbh server so that it can be identified as a server by the system.
· Wait for the connection event when the new device is added to the USB bus.
· Verify the properties of the newly connected device. If the device is the one of interest, mount it through a call to usbh_mount.
· Link the USB device to the corresponding server.
When we detect that our device has been disconnected:
· Unlink the USB device from the corresponding server.
· Unmount the USB device by calling usbh_umount.
An example fully illustrating the management of a USB MSC host server:
THREAD Main(void *arg) { pthread_t pid; pthread_attr_t attr; struct sched_param myNewPriority; struct fsysinit fsysinit; tUSBH_config usb_config; int cnt=0; xprintf("built on %s at %s(%s)\n", __DATE__, __TIME__, demo_type); xprintf("Start USB example\n\r"); pthread_attr_init(&attr); myNewPriority.sched_priority = 5; pthread_attr_setschedparam(&attr, &myNewPriority); pthread_attr_setstacksize(&attr, 2048); /* Start USB host server */ usb_config.usbh_callback = USBH_event; usb_config.USB_baseaddr = (void *)USB0_BASE; if(pthread_create(&pid, &attr, (void*(*)(void*))usbh_server, &usb_config)!=0) { xprintf("pthread_create = %d\n", errno); pthread_exit(0); } if(dir_register("/dev/usb", pid, TYPE_SERVER)==0) { xprintf("dir_register = %d\n", errno); pthread_exit(0); } /* create the File server */ fsysinit.fsi_msgsize = sizeof(struct fsysinit); fsysinit.fsi_datalog = 0x3; fsysinit.fsi_ndrives = 1; //maximum allowed disks pthread_attr_init(&attr); myNewPriority.sched_priority = 5; pthread_attr_setschedparam(&attr, &myNewPriority); pthread_attr_setstacksize(&attr, 2048); if(!pthread_create(&pid, &attr, (void*(*)(void*))_fatfs_server, (char*)&fsysinit)) { if(!dir_register(FSYS_DIRECTORY, pid, TYPE_SERVER)) { xprintf("..Unable to register name of File Server..\n"); xprintf("..Required resource not present - aborting..\n"); pthread_exit((void*)1); } } else { xprintf("..Unable to create File Server..\n"); xprintf("..Required resource for program not present - aborting..\n"); pthread_exit((void*)1); } xprintf("..FAT File server is now created..\n"); pthread_attr_init(&attr); myNewPriority.sched_priority = 3; pthread_attr_setschedparam(&attr, &myNewPriority); pthread_attr_setstacksize(&attr, 2500); pthread_create(&pid, &attr, (void*(*)(void*))usb_thread, 0); pthread_exit((void*)1); } THREAD usb_thread(void) { tUSB_dev_info dev_info; DISK_DRIVER usb_driver; unsigned char dev_cnt, cur_dev=0; int res, DEVNO; int Filenum=0; xprintf("usb_thread start\n"); //clean mounted usb_msc drives list for (DEVNO=0; DEVNO<MAX_DISKN; DEVNO++) mount_disk_addr[DEVNO] = 0; while (1) { if (dev_connected) { //new device was connected dev_cnt = usbh_get_dev_cnt(); //get all connected device count for (cur_dev = 0; cur_dev < dev_cnt; cur_dev ++) { //search MSC class device if (usbh_get_info(cur_dev, &dev_info)) //get info of connected device continue; //can't get info about usb device if (dev_info.Class == USB_CLASS_MASS_STORAGE) { //Found MSC device res = usbh_mount(&dev_info, &usb_driver); //get callback functions for FS read, write etc... if (res) //if devise id already mounted or error has occured - try next continue; xprintf("Found new USB MSC disk.\nAttempting to mount it...\n"); res = fatfs_add_drv(FSYS_MSC_MOUNT, &usb_driver, &DEVNO); //add new disk driver to driver list structure //return DEVNO - local disk driver num if (res) { xprintf("USB: can't mount usb msc device. ERRNO:%d\n",errno); continue; } mount_disk_addr[DEVNO] = dev_info.Dev_n; //add mounted usb disk to "driver num" list xprintf("FatFs allocated driver %x\n",DEVNO); sprintf(USB_mount_path, "%s%d", FSYS_MSC_MOUNT, DEVNO); xprintf("\nMounting Path %s\n", USB_mount_path); // must mount a directory for each mount point, here FSYS_MSC_MOUNT, // unique name for each if ((res = mount(DEVNO, USB_mount_path, 0)) == -1) { xprintf("..Unable to mount flash disk. errno=%d\n", errno); xprintf("..Please fix me..\n"); fatfs_del_drv(USB_mount_path, DEVNO); //del disk driver from driver list structure continue; } xprintf("..done fsys initialization..\n"); } } dev_connected = 0; } sleep(1); } } void USB_event(tUSB_event evt, void *param) { tUSB_dev_info * dev_info = (tUSB_dev_info *)param; int Dev; switch (evt) { case _USBH_CON_EVT: //we have usb device connected { if (dev_info->Class == USB_CLASS_MASS_STORAGE) new_dev_connected = 1; //set flag for main loop xprintf("---- USB device connected:\n"); //print device info xprintf("\tClass %x Subclass %x\n", dev_info->Class, dev_info->Subclass); xprintf("\tPdouctID %x VendorID %x\n", dev_info->pdouctID, dev_info->VendorID); xprintf("\tRevision %x \n", dev_info->Rev); xprintf("\tAddress %x\n", dev_info->Dev_n); xprintf("\tBus %x\n\n", dev_info->Bus); switch (dev_info->Speed) { case 0: xprintf("\tLOW SPEED device\n\n"); break; case 1: xprintf("\tFULL SPEED device\n\n"); break; case 2: xprintf("\tHIGH SPEED device\n\n"); break; } break; } case _USBH_DISCON_EVT: //we have usb device disconnected { xprintf("USB device was disconnected. Class %x\n", dev_info->Class); xprintf("\tAddress %x\n", dev_info->Dev_n); xprintf("\tBus %x\n\n", dev_info->Bus); if (dev_info->Class == USB_CLASS_MASS_STORAGE) //if device class is MSC - begin unmount it { for (Dev=0; Dev < MAX_DISKN; Dev++) //find disconnected disk in "driver num" list if (mount_disk_addr[Dev] == dev_info->Dev_n) // if disk already mounted { mount_disk_addr[Dev] = 0; sprintf(USB_mount_path, "%s%d", FSYS_MSC_MOUNT, Dev); xprintf("Unmountig disk %s...", USB_mount_path); umount(USB_mount_path); //unmount disk from fatfs xprintf("OK\n"); xprintf("FatFs deallocating driver %x..",Dev); fatfs_del_drv(USB_mount_path, Dev); //delete disk driver from fatfs usbh_umount(dev_info->Dev_n, dev_info->Bus); //unmout USB device xprintf("OK\n"); break; } } break; } case _USBH_PWR_EVT: { xprintf("power evt\n"); break; } case _USBH_VBUS_EVT: { xprintf("vbus evt\n"); break; } } }
SEE ALSO
usb usbh_msc usbh_cdc