|
||||||||||
USB handling in RockboxHow Rockbox handles USB slave modeGeneralRockbox is designed for devices with a Universal Mass Storage USB connection. When the user inserts the USB cable, Rockbox should stop accessing the hard drive and enter USB Mode. When the user extracts the cable, Rockbox should continue as normal.The USB threadThere is a dedicated thread that monitors the USB connector and waits for a connection. When it happens, it tells the other threads to stop the disk activity and report back when they are ready. When all threads have responded, the USB thread grants the USB chip control of the hard drive, and waits until the USB connector is extracted. It then tells all threads that it is permitted to access the HD again.The signalling mechanismThe USB thread uses the queue_broadcast() function to signal the other threads. This means that threads that don't have an event queue will not be notified. The USB thread will not enter USB mode until all threads are ready. DirectedGraph Error (25):*DirectedGraphPlugin error:*Step 1: The USB thread sends SYS_USB_CONNECTED to all threads DirectedGraph Error (25):$GV_FILE_PATH environment variable set; exiting 01: 02: This sandboxing mechanism is no longer supported 03: Problem executing /usr/bin/dot: '/usr/bin/dot /home/rockbox/foswiki/working/tmp/DiGraphPluginY4Ws8C37oC.dot -Tpng -o/home/rockbox/foswiki/working/tmp/DGPqWv2YNo03l.png 2> /home/rockbox/foswiki/working/tmp/DiGraphPluginY4Ws8C37oC.dot.err ', got: 04: /usr/bin/dot exited with rc=1 05: *DirectedGraphPlugin error:*Step 2: All threads reply with SYS_USB_CONNECTED_ACK$GV_FILE_PATH environment variable set; exiting 01: 02: This sandboxing mechanism is no longer supported 03: Problem executing /usr/bin/dot: '/usr/bin/dot /home/rockbox/foswiki/working/tmp/DiGraphPluginrFTo0oHbx9.dot -Tpng -o/home/rockbox/foswiki/working/tmp/DGPmt6n7_CQYa.png 2> /home/rockbox/foswiki/working/tmp/DiGraphPluginrFTo0oHbx9.dot.err ', got: 04: /usr/bin/dot exited with rc=1 05: The SYS_USB events
Helper functionsThere are two functions that can handle this for you. Use them.void usb_acknowledge(long id)Call this to send an acknowledge to a USB event. Example:usb_acknowledge(SYS_USB_CONNECTED_ACK); void usb_wait_for_disconnect(struct event_queue *q)Call this to wait until the USB thread sends the SYS_USB_DISCONNECTED event. This function also sends the SYS_USB_DISCONNECTED_ACK event for you. Pass a pointer to your event queue.usb_wait_for_disconnect(&my_queue); int usb_wait_for_disconnect_w_tmo(struct event_queue *q, int ticks)Same as above, but you can specify a timeout where the function returns even if the USB connection is still active. The return value is 1 if there was a timeout, and 0 if the USB was disconnected.ExampleIf you decide that your thread should respond to USB events, do like this:static struct event_queue my_queue; void my_thread(void) { struct event ev; while(1) { queue_wait_w_tmo(&my_queue, &ev, 0); switch(ev.id) { case SYS_USB_CONNECTED: /* Do cleanup, like closing open files */ usb_acknowledge(SYS_USB_CONNECTED_ACK); /* Wait until the USB cable is extracted again */ usb_wait_for_disconnect(&my_queue); break; } } } Special case: the main threadThe main thread is responsible for displaying the "USB Connected" screen while in USB mode. Therefore, the main thread should do it differently. The SYS_USB_CONNECTED event is received in the button queue (which is a regular event queue), so you have to handle it in your button event handler. For your convenience, there is a function that handles all this for you, the default event handler. Just call the default event handler in the default case of your switch. It returns the event that was handled if you need to know, for example if you want to quit the function if it has been in USB mode.Examplewhile (!exit) { key = button_get(); switch( key ) { case BUTTON_STOP: exit = true; break; default: if(default_event_handler(key) == SYS_USB_CONNECTED) { return MYFUNC_ATTACHED_USB; } break; } } r22 - 29 Oct 2023 - 16:24:12 - AdminUser
Copyright © by the contributing authors.
|