Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/ohci/batch.c

    r1387692 r41b96b4  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 /** @addtogroup drvusbohci
     28/** @addtogroup drvusbohcihc
    2929 * @{
    3030 */
     
    3939
    4040#include "batch.h"
    41 #include "utils/malloc32.h"
    42 
    43 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    44 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    45 
    46 #define DEFAULT_ERROR_COUNT 3
    47 usb_transfer_batch_t * batch_get(
    48     ddf_fun_t *fun,
    49                 usb_target_t target,
    50     usb_transfer_type_t transfer_type,
    51                 size_t max_packet_size,
    52     usb_speed_t speed,
    53                 char *buffer,
    54                 size_t buffer_size,
    55                 char *setup_buffer,
    56                 size_t setup_size,
     41
     42static void batch_call_in(batch_t *instance);
     43static void batch_call_out(batch_t *instance);
     44static void batch_call_in_and_dispose(batch_t *instance);
     45static void batch_call_out_and_dispose(batch_t *instance);
     46
     47/** Allocate memory and initialize internal data structure.
     48 *
     49 * @param[in] fun DDF function to pass to callback.
     50 * @param[in] target Device and endpoint target of the transaction.
     51 * @param[in] transfer_type Interrupt, Control or Bulk.
     52 * @param[in] max_packet_size maximum allowed size of data packets.
     53 * @param[in] speed Speed of the transaction.
     54 * @param[in] buffer Data source/destination.
     55 * @param[in] size Size of the buffer.
     56 * @param[in] setup_buffer Setup data source (if not NULL)
     57 * @param[in] setup_size Size of setup_buffer (should be always 8)
     58 * @param[in] func_in function to call on inbound transaction completion
     59 * @param[in] func_out function to call on outbound transaction completion
     60 * @param[in] arg additional parameter to func_in or func_out
     61 * @param[in] manager Pointer to toggle management structure.
     62 * @return Valid pointer if all substructures were successfully created,
     63 * NULL otherwise.
     64 *
     65 * Determines the number of needed packets (TDs). Prepares a transport buffer
     66 * (that is accessible by the hardware). Initializes parameters needed for the
     67 * transaction and callback.
     68 */
     69batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,
     70    usb_transfer_type_t transfer_type, size_t max_packet_size,
     71    usb_speed_t speed, char *buffer, size_t size,
     72    char* setup_buffer, size_t setup_size,
    5773    usbhc_iface_transfer_in_callback_t func_in,
    58     usbhc_iface_transfer_out_callback_t func_out,
    59                 void *arg,
    60                 usb_device_keeper_t *manager
    61                 )
    62 {
     74    usbhc_iface_transfer_out_callback_t func_out, void *arg
     75    )
     76{
     77        assert(func_in == NULL || func_out == NULL);
     78        assert(func_in != NULL || func_out != NULL);
     79
    6380#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    64         if (ptr == NULL) { \
    65                 usb_log_error(message); \
    66                 if (instance) { \
    67                         batch_dispose(instance); \
    68                 } \
    69                 return NULL; \
    70         } else (void)0
    71 
    72         usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
     81        if (ptr == NULL) { \
     82                usb_log_error(message); \
     83                if (instance) { \
     84                        batch_dispose(instance); \
     85                } \
     86                return NULL; \
     87        } else (void)0
     88
     89        batch_t *instance = malloc(sizeof(batch_t));
    7390        CHECK_NULL_DISPOSE_RETURN(instance,
    7491            "Failed to allocate batch instance.\n");
    75         usb_transfer_batch_init(instance, target, transfer_type, speed, max_packet_size,
    76             buffer, NULL, buffer_size, NULL, setup_size, func_in,
    77             func_out, arg, fun, NULL);
    78 
    79         if (buffer_size > 0) {
    80                 instance->transport_buffer = malloc32(buffer_size);
    81                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    82                     "Failed to allocate device accessible buffer.\n");
    83         }
    84 
    85         if (setup_size > 0) {
    86                 instance->setup_buffer = malloc32(setup_size);
    87                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    88                     "Failed to allocate device accessible setup buffer.\n");
    89                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
    90         }
    91 
    92 
     92        bzero(instance, sizeof(batch_t));
     93
     94        if (size > 0) {
     95                /* TODO: use device accessible malloc here */
     96                instance->transport_buffer = malloc(size);
     97                CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
     98                    "Failed to allocate device accessible buffer.\n");
     99        }
     100
     101        if (setup_size > 0) {
     102                /* TODO: use device accessible malloc here */
     103                instance->setup_buffer = malloc(setup_size);
     104                CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
     105                    "Failed to allocate device accessible setup buffer.\n");
     106                memcpy(instance->setup_buffer, setup_buffer, setup_size);
     107        }
     108
     109        link_initialize(&instance->link);
     110
     111        instance->max_packet_size = max_packet_size;
     112        instance->target = target;
     113        instance->transfer_type = transfer_type;
     114        instance->buffer = buffer;
     115        instance->buffer_size = size;
     116        instance->setup_size = setup_size;
     117        instance->fun = fun;
     118        instance->arg = arg;
     119        instance->speed = speed;
     120        instance->callback_out = func_out;
     121        instance->callback_in = func_in;
     122
     123        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
     124            instance, target.address, target.endpoint);
    93125        return instance;
    94126}
    95127/*----------------------------------------------------------------------------*/
    96 void batch_dispose(usb_transfer_batch_t *instance)
    97 {
    98         assert(instance);
    99         free32(instance->transport_buffer);
    100         free32(instance->setup_buffer);
    101         free(instance);
    102 }
    103 /*----------------------------------------------------------------------------*/
    104 void batch_control_write(usb_transfer_batch_t *instance)
     128/** Mark batch as finished and continue with next step.
     129 *
     130 * @param[in] instance Batch structure to use.
     131 *
     132 */
     133void batch_finish(batch_t *instance, int error)
     134{
     135        assert(instance);
     136        instance->error = error;
     137        instance->next_step(instance);
     138}
     139/*----------------------------------------------------------------------------*/
     140/** Check batch TDs for activity.
     141 *
     142 * @param[in] instance Batch structure to use.
     143 * @return False, if there is an active TD, true otherwise.
     144 *
     145 * Walk all TDs. Stop with false if there is an active one (it is to be
     146 * processed). Stop with true if an error is found. Return true if the last TS
     147 * is reached.
     148 */
     149bool batch_is_complete(batch_t *instance)
     150{
     151        assert(instance);
     152        /* TODO: implement */
     153        return true;
     154}
     155/*----------------------------------------------------------------------------*/
     156/** Prepares control write transaction.
     157 *
     158 * @param[in] instance Batch structure to use.
     159 *
     160 * Uses genercir control function with pids OUT and IN.
     161 */
     162void batch_control_write(batch_t *instance)
    105163{
    106164        assert(instance);
     
    113171}
    114172/*----------------------------------------------------------------------------*/
    115 void batch_control_read(usb_transfer_batch_t *instance)
     173/** Prepares control read transaction.
     174 *
     175 * @param[in] instance Batch structure to use.
     176 *
     177 * Uses generic control with pids IN and OUT.
     178 */
     179void batch_control_read(batch_t *instance)
    116180{
    117181        assert(instance);
    118182        instance->next_step = batch_call_in_and_dispose;
    119183        /* TODO: implement */
    120         usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    121 }
    122 /*----------------------------------------------------------------------------*/
    123 void batch_interrupt_in(usb_transfer_batch_t *instance)
    124 {
    125         assert(instance);
    126         instance->direction = USB_DIRECTION_IN;
     184        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
     185}
     186/*----------------------------------------------------------------------------*/
     187/** Prepare interrupt in transaction.
     188 *
     189 * @param[in] instance Batch structure to use.
     190 *
     191 * Data transaction with PID_IN.
     192 */
     193void batch_interrupt_in(batch_t *instance)
     194{
     195        assert(instance);
     196        /* TODO: implement */
    127197        instance->next_step = batch_call_in_and_dispose;
    128         /* TODO: implement */
    129198        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    130199}
    131200/*----------------------------------------------------------------------------*/
    132 void batch_interrupt_out(usb_transfer_batch_t *instance)
    133 {
    134         assert(instance);
    135         instance->direction = USB_DIRECTION_OUT;
     201/** Prepare interrupt out transaction.
     202 *
     203 * @param[in] instance Batch structure to use.
     204 *
     205 * Data transaction with PID_OUT.
     206 */
     207void batch_interrupt_out(batch_t *instance)
     208{
     209        assert(instance);
    136210        /* We are data out, we are supposed to provide data */
    137211        memcpy(instance->transport_buffer, instance->buffer,
     
    142216}
    143217/*----------------------------------------------------------------------------*/
    144 void batch_bulk_in(usb_transfer_batch_t *instance)
    145 {
    146         assert(instance);
    147         instance->direction = USB_DIRECTION_IN;
     218/** Prepare bulk in transaction.
     219 *
     220 * @param[in] instance Batch structure to use.
     221 *
     222 * Data transaction with PID_IN.
     223 */
     224void batch_bulk_in(batch_t *instance)
     225{
     226        assert(instance);
    148227        instance->next_step = batch_call_in_and_dispose;
    149228        /* TODO: implement */
     
    151230}
    152231/*----------------------------------------------------------------------------*/
    153 void batch_bulk_out(usb_transfer_batch_t *instance)
    154 {
    155         assert(instance);
    156         instance->direction = USB_DIRECTION_IN;
    157         instance->next_step = batch_call_in_and_dispose;
    158         /* TODO: implement */
    159         usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
     232/** Prepare bulk out transaction.
     233 *
     234 * @param[in] instance Batch structure to use.
     235 *
     236 * Data transaction with PID_OUT.
     237 */
     238void batch_bulk_out(batch_t *instance)
     239{
     240        assert(instance);
     241        /* We are data out, we are supposed to provide data */
     242        memcpy(instance->transport_buffer, instance->buffer,
     243            instance->buffer_size);
     244        instance->next_step = batch_call_out_and_dispose;
     245        /* TODO: implement */
     246        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
     247}
     248/*----------------------------------------------------------------------------*/
     249/** Prepare data, get error status and call callback in.
     250 *
     251 * @param[in] instance Batch structure to use.
     252 * Copies data from transport buffer, and calls callback with appropriate
     253 * parameters.
     254 */
     255void batch_call_in(batch_t *instance)
     256{
     257        assert(instance);
     258        assert(instance->callback_in);
     259
     260        /* We are data in, we need data */
     261        memcpy(instance->buffer, instance->transport_buffer,
     262            instance->buffer_size);
     263
     264        int err = instance->error;
     265        usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n",
     266            instance, instance->transfer_type, str_error(err), err,
     267            instance->transfered_size);
     268
     269        instance->callback_in(
     270            instance->fun, err, instance->transfered_size, instance->arg);
     271}
     272/*----------------------------------------------------------------------------*/
     273/** Get error status and call callback out.
     274 *
     275 * @param[in] instance Batch structure to use.
     276 */
     277void batch_call_out(batch_t *instance)
     278{
     279        assert(instance);
     280        assert(instance->callback_out);
     281
     282        int err = instance->error;
     283        usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n",
     284            instance, instance->transfer_type, str_error(err), err);
     285        instance->callback_out(instance->fun,
     286            err, instance->arg);
    160287}
    161288/*----------------------------------------------------------------------------*/
     
    164291 * @param[in] instance Batch structure to use.
    165292 */
    166 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    167 {
    168         assert(instance);
    169         usb_transfer_batch_call_in(instance);
     293void batch_call_in_and_dispose(batch_t *instance)
     294{
     295        assert(instance);
     296        batch_call_in(instance);
    170297        batch_dispose(instance);
    171298}
     
    175302 * @param[in] instance Batch structure to use.
    176303 */
    177 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    178 {
    179         assert(instance);
    180         usb_transfer_batch_call_out(instance);
     304void batch_call_out_and_dispose(batch_t *instance)
     305{
     306        assert(instance);
     307        batch_call_out(instance);
    181308        batch_dispose(instance);
     309}
     310/*----------------------------------------------------------------------------*/
     311/** Correctly dispose all used data structures.
     312 *
     313 * @param[in] instance Batch structure to use.
     314 */
     315void batch_dispose(batch_t *instance)
     316{
     317        assert(instance);
     318        usb_log_debug("Batch(%p) disposing.\n", instance);
     319        if (instance->setup_buffer)
     320                free(instance->setup_buffer);
     321        if (instance->transport_buffer)
     322                free(instance->transport_buffer);
     323        free(instance);
    182324}
    183325/**
Note: See TracChangeset for help on using the changeset viewer.