Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/usb/src/usbdrvreq.c

    r82783b0 r863d45e  
    3636#include <errno.h>
    3737
     38/**  Prepare USB target for control endpoint.
     39 *
     40 * @param name Variable name with the USB target.
     41 * @param target_address Target USB address.
     42 */
     43#define PREPARE_TARGET(name, target_address) \
     44        usb_target_t name = { \
     45                .address = target_address, \
     46                .endpoint = 0 \
     47        }
     48
     49/** Prepare setup packet.
     50 *
     51 * @param name Variable name with the setup packet.
     52 * @param p_direction Data transfer direction.
     53 * @param p_type Request type (standard/class/vendor)
     54 * @param p_recipient Recipient of the request.
     55 * @param p_request Request.
     56 * @param p_value wValue field of setup packet.
     57 * @param p_index wIndex field of setup packet.
     58 * @param p_length Length of extra data.
     59 */
     60#define PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
     61    p_request, p_value, p_index, p_length) \
     62        usb_device_request_setup_packet_t setup_packet = { \
     63                .request_type = \
     64                        ((p_direction) == USB_DIRECTION_IN ? 128 : 0) \
     65                        | ((p_type) << 5) \
     66                        | (p_recipient), \
     67                .request = (p_request), \
     68                { .value = (p_value) }, \
     69                .index = (p_index), \
     70                .length = (p_length) \
     71        }
     72
     73/** Prepare setup packet.
     74 *
     75 * @param name Variable name with the setup packet.
     76 * @param p_direction Data transfer direction.
     77 * @param p_type Request type (standard/class/vendor)
     78 * @param p_recipient Recipient of the request.
     79 * @param p_request Request.
     80 * @param p_value_low wValue field of setup packet (low byte).
     81 * @param p_value_high wValue field of setup packet (high byte).
     82 * @param p_index wIndex field of setup packet.
     83 * @param p_length Length of extra data.
     84 */
     85#define PREPARE_SETUP_PACKET_LOHI(name, p_direction, p_type, p_recipient, \
     86    p_request, p_value_low, p_value_high, p_index, p_length) \
     87        PREPARE_SETUP_PACKET(name, p_direction, p_type, p_recipient, \
     88            p_request, (p_value_low) | ((p_value_high) << 8), \
     89            p_index, p_length)
     90
     91/** Retrieve status of a USB device.
     92 *
     93 * @param[in] hc_phone Open phone to HC driver.
     94 * @param[in] address Device address.
     95 * @param[in] recipient Recipient of the request.
     96 * @param[in] recipient_index Index of @p recipient.
     97 * @param[out] status Status (see figure 9-4 in USB 1.1 specification).
     98 * @return Error code.
     99 */
     100int usb_drv_req_get_status(int hc_phone, usb_address_t address,
     101    usb_request_recipient_t recipient, uint16_t recipient_index,
     102    uint16_t *status)
     103{
     104        if (status == NULL) {
     105                return EBADMEM;
     106        }
     107
     108        PREPARE_TARGET(target, address);
     109
     110        PREPARE_SETUP_PACKET(setup_packet,
     111            USB_DIRECTION_IN, USB_REQUEST_TYPE_STANDARD,
     112            recipient, USB_DEVREQ_GET_STATUS, 0, recipient_index, 2);
     113
     114        size_t transfered;
     115        uint16_t tmp_status;
     116        int rc = usb_drv_psync_control_read(hc_phone, target,
     117            &setup_packet, sizeof(setup_packet), &tmp_status, 2, &transfered);
     118        if (rc != EOK) {
     119                return rc;
     120        }
     121        if (transfered != 2) {
     122                return ERANGE;
     123        }
     124
     125        *status = tmp_status;
     126
     127        return EOK;
     128}
     129
     130/** Clear or disable USB device feature.
     131 *
     132 * @param[in] hc_phone Open phone to HC driver.
     133 * @param[in] address Device address.
     134 * @param[in] recipient Recipient of the request.
     135 * @param[in] selector Feature selector.
     136 * @param[in] index Index of @p recipient.
     137 * @return Error code.
     138 */
     139int usb_drv_req_clear_feature(int hc_phone, usb_address_t address,
     140    usb_request_recipient_t recipient,
     141    uint16_t selector, uint16_t index)
     142{
     143        PREPARE_TARGET(target, address);
     144
     145        PREPARE_SETUP_PACKET(setup_packet,
     146            USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
     147            recipient, USB_DEVREQ_CLEAR_FEATURE, selector, index, 0);
     148
     149        int rc = usb_drv_psync_control_write(hc_phone, target,
     150            &setup_packet, sizeof(setup_packet), NULL, 0);
     151
     152        return rc;
     153}
     154
     155/** Set or enable USB device feature.
     156 *
     157 * @param[in] hc_phone Open phone to HC driver.
     158 * @param[in] address Device address.
     159 * @param[in] recipient Recipient of the request.
     160 * @param[in] selector Feature selector.
     161 * @param[in] index Index of @p recipient.
     162 * @return Error code.
     163 */
     164int usb_drv_req_set_feature(int hc_phone, usb_address_t address,
     165    usb_request_recipient_t recipient,
     166    uint16_t selector, uint16_t index)
     167{
     168        PREPARE_TARGET(target, address);
     169
     170        PREPARE_SETUP_PACKET(setup_packet,
     171            USB_DIRECTION_OUT, USB_REQUEST_TYPE_STANDARD,
     172            recipient, USB_DEVREQ_SET_FEATURE, selector, index, 0);
     173
     174        int rc = usb_drv_psync_control_write(hc_phone, target,
     175            &setup_packet, sizeof(setup_packet), NULL, 0);
     176
     177        return rc;
     178}
     179
    38180/** Change address of connected device.
    39181 *
     
    44186 * @see usb_drv_bind_address
    45187 *
    46  * @param phone Open phone to HC driver.
    47  * @param old_address Current address.
    48  * @param address Address to be set.
     188 * @param[in] phone Open phone to HC driver.
     189 * @param[in] old_address Current address.
     190 * @param[in] address Address to be set.
    49191 * @return Error code.
    50192 */
     
    52194    usb_address_t new_address)
    53195{
    54         /* Prepare the target. */
    55         usb_target_t target = {
    56                 .address = old_address,
    57                 .endpoint = 0
    58         };
    59 
    60         /* Prepare the setup packet. */
    61         usb_device_request_setup_packet_t setup_packet = {
    62                 .request_type = 0,
    63                 .request = USB_DEVREQ_SET_ADDRESS,
    64                 .index = 0,
    65                 .length = 0,
    66         };
    67         setup_packet.value = new_address;
     196        PREPARE_TARGET(target, old_address);
     197
     198        PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_OUT,
     199            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     200            USB_DEVREQ_SET_ADDRESS, new_address, 0, 0);
    68201
    69202        int rc = usb_drv_psync_control_write(phone, target,
     
    73206}
    74207
     208/** Retrieve USB descriptor of connected USB device.
     209 *
     210 * @param[in] hc_phone Open phone to HC driver.
     211 * @param[in] address Device address.
     212 * @param[in] request_type Request type (standard/class/vendor).
     213 * @param[in] descriptor_type Descriptor type (device/configuration/HID/...).
     214 * @param[in] descriptor_index Descriptor index.
     215 * @param[in] language Language index.
     216 * @param[out] buffer Buffer where to store the retrieved descriptor.
     217 * @param[in] size Size of the @p buffer.
     218 * @param[out] actual_size Number of bytes actually transferred.
     219 * @return Error code.
     220 */
     221int usb_drv_req_get_descriptor(int hc_phone, usb_address_t address,
     222    usb_request_type_t request_type,
     223    uint8_t descriptor_type, uint8_t descriptor_index,
     224    uint16_t language,
     225    void *buffer, size_t size, size_t *actual_size)
     226{
     227        if (buffer == NULL) {
     228                return EBADMEM;
     229        }
     230        if (size == 0) {
     231                return EINVAL;
     232        }
     233
     234        // FIXME: check that size is not too big
     235
     236        PREPARE_TARGET(target, address);
     237
     238        PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_IN,
     239            request_type, USB_REQUEST_RECIPIENT_DEVICE,
     240            USB_DEVREQ_GET_DESCRIPTOR, descriptor_index, descriptor_type,
     241            language, size);
     242
     243        int rc = usb_drv_psync_control_read(hc_phone, target,
     244            &setup_packet, sizeof(setup_packet),
     245            buffer, size, actual_size);
     246       
     247        return rc;
     248}
     249
    75250/** Retrieve device descriptor of connected USB device.
    76251 *
    77252 * @param[in] phone Open phone to HC driver.
    78  * @param[in] address Device USB address.
     253 * @param[in] address Device address.
    79254 * @param[out] descriptor Storage for the device descriptor.
    80255 * @return Error code.
     
    87262                return EBADMEM;
    88263        }
    89 
    90         /* Prepare the target. */
    91         usb_target_t target = {
    92                 .address = address,
    93                 .endpoint = 0
    94         };
    95 
    96         /* Prepare the setup packet. */
    97         usb_device_request_setup_packet_t setup_packet = {
    98                 .request_type = 128,
    99                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    100                 .index = 0,
    101                 .length = sizeof(usb_standard_device_descriptor_t)
    102         };
    103         setup_packet.value_high = USB_DESCTYPE_DEVICE;
    104         setup_packet.value_low = 0;
    105 
    106         /* Prepare local descriptor. */
     264       
    107265        size_t actually_transferred = 0;
    108266        usb_standard_device_descriptor_t descriptor_tmp;
    109 
    110         /* Perform the control read transaction. */
    111         int rc = usb_drv_psync_control_read(phone, target,
    112             &setup_packet, sizeof(setup_packet),
    113             &descriptor_tmp, sizeof(descriptor_tmp), &actually_transferred);
     267        int rc = usb_drv_req_get_descriptor(phone, address,
     268            USB_REQUEST_TYPE_STANDARD,
     269            USB_DESCTYPE_DEVICE, 0,
     270            0,
     271            &descriptor_tmp, sizeof(descriptor_tmp),
     272            &actually_transferred);
    114273
    115274        if (rc != EOK) {
     
    137296 *
    138297 * @param[in] phone Open phone to HC driver.
    139  * @param[in] address Device USB address.
     298 * @param[in] address Device address.
    140299 * @param[in] index Configuration descriptor index.
    141300 * @param[out] descriptor Storage for the configuration descriptor.
     
    150309                return EBADMEM;
    151310        }
    152 
    153         /* Prepare the target. */
    154         usb_target_t target = {
    155                 .address = address,
    156                 .endpoint = 0
    157         };
    158 
    159         /* Prepare the setup packet. */
    160         usb_device_request_setup_packet_t setup_packet = {
    161                 .request_type = 128,
    162                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    163                 .index = 0,
    164                 .length = sizeof(usb_standard_configuration_descriptor_t)
    165         };
    166         setup_packet.value_high = USB_DESCTYPE_CONFIGURATION;
    167         setup_packet.value_low = index;
    168 
    169         /* Prepare local descriptor. */
     311       
    170312        size_t actually_transferred = 0;
    171313        usb_standard_configuration_descriptor_t descriptor_tmp;
    172 
    173         /* Perform the control read transaction. */
    174         int rc = usb_drv_psync_control_read(phone, target,
    175             &setup_packet, sizeof(setup_packet),
    176             &descriptor_tmp, sizeof(descriptor_tmp), &actually_transferred);
     314        int rc = usb_drv_req_get_descriptor(phone, address,
     315            USB_REQUEST_TYPE_STANDARD,
     316            USB_DESCTYPE_CONFIGURATION, 0,
     317            0,
     318            &descriptor_tmp, sizeof(descriptor_tmp),
     319            &actually_transferred);
    177320
    178321        if (rc != EOK) {
     
    195338 *
    196339 * @warning The @p buffer might be touched (i.e. its contents changed)
    197  * even when error occurres.
     340 * even when error occurs.
    198341 *
    199342 * @param[in] phone Open phone to HC driver.
    200  * @param[in] address Device USB address.
     343 * @param[in] address Device address.
    201344 * @param[in] index Configuration descriptor index.
    202345 * @param[out] buffer Buffer for the whole configuration descriptor.
     
    210353    void *buffer, size_t buffer_size, size_t *actual_buffer_size)
    211354{
    212         if (buffer == NULL) {
     355        int rc = usb_drv_req_get_descriptor(phone, address,
     356            USB_REQUEST_TYPE_STANDARD,
     357            USB_DESCTYPE_CONFIGURATION, 0,
     358            0,
     359            buffer, buffer_size,
     360            actual_buffer_size);
     361
     362        return rc;
     363}
     364
     365/** Update existing descriptor of a USB device.
     366 *
     367 * @param[in] hc_phone Open phone to HC driver.
     368 * @param[in] address Device address.
     369 * @param[in] descriptor_type Descriptor type (device/configuration/...).
     370 * @param[in] descriptor_index Descriptor index.
     371 * @param[in] language Language index.
     372 * @param[in] descriptor Actual descriptor data.
     373 * @param[in] descriptor_size Descriptor size.
     374 * @return Error code.
     375 */
     376int usb_drv_req_set_descriptor(int hc_phone, usb_address_t address,
     377    uint8_t descriptor_type, uint8_t descriptor_index,
     378    uint16_t language,
     379    void *descriptor, size_t descriptor_size)
     380{
     381        // FIXME: check that descriptor is not too big
     382
     383        PREPARE_TARGET(target, address);
     384
     385        PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
     386            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     387            USB_DEVREQ_SET_DESCRIPTOR, descriptor_index, descriptor_type,
     388            language, descriptor_size);
     389
     390        int rc = usb_drv_psync_control_write(hc_phone, target,
     391            &setup_packet, sizeof(setup_packet),
     392            descriptor, descriptor_size);
     393
     394        return rc;
     395}
     396
     397/** Determine current configuration value of USB device.
     398 *
     399 * @param[in] hc_phone Open phone to HC driver.
     400 * @param[in] address Device address.
     401 * @param[out] configuration_value Current configuration value.
     402 * @return Error code.
     403 */
     404int usb_drv_req_get_configuration(int hc_phone, usb_address_t address,
     405    uint8_t *configuration_value)
     406{
     407        if (configuration_value == NULL) {
    213408                return EBADMEM;
    214409        }
    215410
    216         /* Prepare the target. */
    217         usb_target_t target = {
    218                 .address = address,
    219                 .endpoint = 0
    220         };
    221 
    222         /* Prepare the setup packet. */
    223         usb_device_request_setup_packet_t setup_packet = {
    224                 .request_type = 128,
    225                 .request = USB_DEVREQ_GET_DESCRIPTOR,
    226                 .index = 0,
    227                 .length = buffer_size
    228         };
    229         setup_packet.value_high = USB_DESCTYPE_CONFIGURATION;
    230         setup_packet.value_low = index;
    231 
    232         /* Perform the control read transaction. */
    233         int rc = usb_drv_psync_control_read(phone, target,
    234             &setup_packet, sizeof(setup_packet),
    235             buffer, buffer_size, actual_buffer_size);
    236 
    237         return rc;
    238 }
    239 
     411        PREPARE_TARGET(target, address);
     412
     413        PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
     414            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     415            USB_DEVREQ_GET_CONFIGURATION, 0, 0, 1);
     416
     417        uint8_t value;
     418        size_t transfered;
     419        int rc = usb_drv_psync_control_read(hc_phone, target,
     420            &setup_packet, sizeof(setup_packet), &value, 1, &transfered);
     421
     422        if (rc != EOK) {
     423                return rc;
     424        }
     425
     426        if (transfered != 1) {
     427                return ERANGE;
     428        }
     429
     430        *configuration_value = value;
     431
     432        return EOK;
     433}
     434
     435/** Set configuration of USB device.
     436 *
     437 * @param[in] hc_phone Open phone to HC driver.
     438 * @param[in] address Device address.
     439 * @param[in] configuration_value New configuration value.
     440 * @return Error code.
     441 */
     442int usb_drv_req_set_configuration(int hc_phone, usb_address_t address,
     443    uint8_t configuration_value)
     444{
     445        PREPARE_TARGET(target, address);
     446
     447        PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
     448            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_DEVICE,
     449            USB_DEVREQ_SET_CONFIGURATION, configuration_value, 0,
     450            0, 0);
     451
     452        int rc = usb_drv_psync_control_write(hc_phone, target,
     453            &setup_packet, sizeof(setup_packet), NULL, 0);
     454
     455        return rc;
     456}
     457
     458/** Determine alternate setting of USB device interface.
     459 *
     460 * @param[in] hc_phone Open phone to HC driver.
     461 * @param[in] address Device address.
     462 * @param[in] interface_index Interface index.
     463 * @param[out] alternate_setting Value of alternate setting.
     464 * @return Error code.
     465 */
     466int usb_drv_req_get_interface(int hc_phone, usb_address_t address,
     467    uint16_t interface_index, uint8_t *alternate_setting)
     468{
     469        if (alternate_setting == NULL) {
     470                return EBADMEM;
     471        }
     472
     473        PREPARE_TARGET(target, address);
     474
     475        PREPARE_SETUP_PACKET(setup_packet, USB_DIRECTION_IN,
     476            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     477            USB_DEVREQ_GET_INTERFACE, 0, interface_index, 1);
     478
     479        uint8_t alternate;
     480        size_t transfered;
     481        int rc = usb_drv_psync_control_read(hc_phone, target,
     482            &setup_packet, sizeof(setup_packet), &alternate, 1, &transfered);
     483
     484        if (rc != EOK) {
     485                return rc;
     486        }
     487
     488        if (transfered != 1) {
     489                return ERANGE;
     490        }
     491
     492        *alternate_setting = alternate;
     493
     494        return EOK;
     495}
     496
     497/** Select an alternate setting of USB device interface.
     498 *
     499 * @param[in] hc_phone Open phone to HC driver.
     500 * @param[in] address Device address.
     501 * @param[in] interface_index Interface index.
     502 * @param[in] alternate_setting Value of alternate setting.
     503 * @return Error code.
     504 */
     505int usb_drv_req_set_interface(int hc_phone, usb_address_t address,
     506    uint16_t interface_index, uint8_t alternate_setting)
     507{
     508        PREPARE_TARGET(target, address);
     509
     510        PREPARE_SETUP_PACKET_LOHI(setup_packet, USB_DIRECTION_OUT,
     511            USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE,
     512            USB_DEVREQ_SET_INTERFACE, alternate_setting, 0,
     513            0, 0);
     514
     515        int rc = usb_drv_psync_control_write(hc_phone, target,
     516            &setup_packet, sizeof(setup_packet), NULL, 0);
     517
     518        return rc;
     519}
    240520
    241521/**
Note: See TracChangeset for help on using the changeset viewer.