iPXE
usbhid.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <string.h>
00027 #include <errno.h>
00028 #include <ipxe/usb.h>
00029 #include <ipxe/usbhid.h>
00030 
00031 /** @file
00032  *
00033  * USB human interface devices (HID)
00034  *
00035  */
00036 
00037 /**
00038  * Open USB human interface device
00039  *
00040  * @v hid               USB human interface device
00041  * @ret rc              Return status code
00042  */
00043 int usbhid_open ( struct usb_hid *hid ) {
00044         int rc;
00045 
00046         /* Open interrupt IN endpoint */
00047         if ( ( rc = usb_endpoint_open ( &hid->in ) ) != 0 ) {
00048                 DBGC ( hid, "HID %s could not open interrupt IN: %s\n",
00049                        hid->func->name, strerror ( rc ) );
00050                 goto err_open_in;
00051         }
00052 
00053         /* Refill interrupt IN endpoint */
00054         if ( ( rc = usb_refill ( &hid->in ) ) != 0 ) {
00055                 DBGC ( hid, "HID %s could not refill interrupt IN: %s\n",
00056                        hid->func->name, strerror ( rc ) );
00057                 goto err_refill_in;
00058         }
00059 
00060         /* Open interrupt OUT endpoint, if applicable */
00061         if ( hid->out.usb &&
00062              ( ( rc = usb_endpoint_open ( &hid->out ) ) != 0 ) ) {
00063                 DBGC ( hid, "HID %s could not open interrupt OUT: %s\n",
00064                        hid->func->name, strerror ( rc ) );
00065                 goto err_open_out;
00066         }
00067 
00068         return 0;
00069 
00070         usb_endpoint_close ( &hid->out );
00071  err_open_out:
00072  err_refill_in:
00073         usb_endpoint_close ( &hid->in );
00074  err_open_in:
00075         return rc;
00076 }
00077 
00078 /**
00079  * Close USB human interface device
00080  *
00081  * @v hid               USB human interface device
00082  */
00083 void usbhid_close ( struct usb_hid *hid ) {
00084 
00085         /* Close interrupt OUT endpoint, if applicable */
00086         if ( hid->out.usb )
00087                 usb_endpoint_close ( &hid->out );
00088 
00089         /* Close interrupt IN endpoint */
00090         usb_endpoint_close ( &hid->in );
00091 }
00092 
00093 /**
00094  * Refill USB human interface device endpoints
00095  *
00096  * @v hid               USB human interface device
00097  * @ret rc              Return status code
00098  */
00099 int usbhid_refill ( struct usb_hid *hid ) {
00100         int rc;
00101 
00102         /* Refill interrupt IN endpoint */
00103         if ( ( rc = usb_refill ( &hid->in ) ) != 0 )
00104                 return rc;
00105 
00106         /* Refill interrupt OUT endpoint, if applicable */
00107         if ( hid->out.usb && ( ( rc = usb_refill ( &hid->out ) ) != 0 ) )
00108                 return rc;
00109 
00110         return 0;
00111 }
00112 
00113 /**
00114  * Describe USB human interface device
00115  *
00116  * @v hid               USB human interface device
00117  * @v config            Configuration descriptor
00118  * @ret rc              Return status code
00119  */
00120 int usbhid_describe ( struct usb_hid *hid,
00121                       struct usb_configuration_descriptor *config ) {
00122         struct usb_interface_descriptor *desc;
00123         int rc;
00124 
00125         /* Locate interface descriptor */
00126         desc = usb_interface_descriptor ( config, hid->func->interface[0], 0 );
00127         if ( ! desc ) {
00128                 DBGC ( hid, "HID %s has no interface descriptor\n",
00129                        hid->func->name );
00130                 return -EINVAL;
00131         }
00132 
00133         /* Describe interrupt IN endpoint */
00134         if ( ( rc = usb_endpoint_described ( &hid->in, config, desc,
00135                                              USB_INTERRUPT_IN, 0 ) ) != 0 ) {
00136                 DBGC ( hid, "HID %s could not describe interrupt IN: %s\n",
00137                        hid->func->name, strerror ( rc ) );
00138                 return rc;
00139         }
00140 
00141         /* Describe interrupt OUT endpoint, if applicable */
00142         if ( hid->out.usb &&
00143              ( ( rc = usb_endpoint_described ( &hid->out, config, desc,
00144                                                USB_INTERRUPT_OUT, 0 ) ) != 0 )){
00145                 DBGC ( hid, "HID %s could not describe interrupt OUT: %s\n",
00146                        hid->func->name, strerror ( rc ) );
00147                 return rc;
00148         }
00149 
00150         return 0;
00151 }