Commit 89b9b79f340f5799c29ab8178231377026c301e4

Authored by aliguori
1 parent 4b096fc9

usb: generic packet handler cleanup and documentation (Max Krasnyansky)

A bit better documentation of the USB device API, namely
return codes.
Rewrite of usb_generic_handle_packet() to make it more
reable and easier to follow.

Signed-off-by: Max Krasnyansky <maxk@kernel.org>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5049 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 179 additions and 121 deletions
hw/usb.c
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 * 3 *
4 * Copyright (c) 2005 Fabrice Bellard 4 * Copyright (c) 2005 Fabrice Bellard
5 * 5 *
  6 + * 2008 Generic packet handler rewrite by Max Krasnyansky
  7 + *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal 9 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights 10 * in the Software without restriction, including without limitation the rights
@@ -30,6 +32,7 @@ void usb_attach(USBPort *port, USBDevice *dev) @@ -30,6 +32,7 @@ void usb_attach(USBPort *port, USBDevice *dev)
30 } 32 }
31 33
32 /**********************/ 34 /**********************/
  35 +
33 /* generic USB device helpers (you are not forced to use them when 36 /* generic USB device helpers (you are not forced to use them when
34 writing your USB device driver, but they help handling the 37 writing your USB device driver, but they help handling the
35 protocol) 38 protocol)
@@ -39,141 +42,164 @@ void usb_attach(USBPort *port, USBDevice *dev) @@ -39,141 +42,164 @@ void usb_attach(USBPort *port, USBDevice *dev)
39 #define SETUP_STATE_DATA 1 42 #define SETUP_STATE_DATA 1
40 #define SETUP_STATE_ACK 2 43 #define SETUP_STATE_ACK 2
41 44
42 -int usb_generic_handle_packet(USBDevice *s, USBPacket *p) 45 +static int do_token_setup(USBDevice *s, USBPacket *p)
  46 +{
  47 + int request, value, index;
  48 + int ret = 0;
  49 +
  50 + if (p->len != 8)
  51 + return USB_RET_STALL;
  52 +
  53 + memcpy(s->setup_buf, p->data, 8);
  54 + s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];
  55 + s->setup_index = 0;
  56 +
  57 + request = (s->setup_buf[0] << 8) | s->setup_buf[1];
  58 + value = (s->setup_buf[3] << 8) | s->setup_buf[2];
  59 + index = (s->setup_buf[5] << 8) | s->setup_buf[4];
  60 +
  61 + if (s->setup_buf[0] & USB_DIR_IN) {
  62 + ret = s->handle_control(s, request, value, index,
  63 + s->setup_len, s->data_buf);
  64 + if (ret < 0)
  65 + return ret;
  66 +
  67 + if (ret < s->setup_len)
  68 + s->setup_len = ret;
  69 + s->setup_state = SETUP_STATE_DATA;
  70 + } else {
  71 + if (s->setup_len == 0)
  72 + s->setup_state = SETUP_STATE_ACK;
  73 + else
  74 + s->setup_state = SETUP_STATE_DATA;
  75 + }
  76 +
  77 + return ret;
  78 +}
  79 +
  80 +static int do_token_in(USBDevice *s, USBPacket *p)
43 { 81 {
44 - int l, ret = 0;  
45 - int len = p->len;  
46 - uint8_t *data = p->data; 82 + int request, value, index;
  83 + int ret = 0;
  84 +
  85 + if (p->devep != 0)
  86 + return s->handle_data(s, p);
  87 +
  88 + request = (s->setup_buf[0] << 8) | s->setup_buf[1];
  89 + value = (s->setup_buf[3] << 8) | s->setup_buf[2];
  90 + index = (s->setup_buf[5] << 8) | s->setup_buf[4];
  91 +
  92 + switch(s->setup_state) {
  93 + case SETUP_STATE_ACK:
  94 + if (!(s->setup_buf[0] & USB_DIR_IN)) {
  95 + s->setup_state = SETUP_STATE_IDLE;
  96 + ret = s->handle_control(s, request, value, index,
  97 + s->setup_len, s->data_buf);
  98 + if (ret > 0)
  99 + return 0;
  100 + return ret;
  101 + }
  102 +
  103 + /* return 0 byte */
  104 + return 0;
  105 +
  106 + case SETUP_STATE_DATA:
  107 + if (s->setup_buf[0] & USB_DIR_IN) {
  108 + int len = s->setup_len - s->setup_index;
  109 + if (len > p->len)
  110 + len = p->len;
  111 + memcpy(p->data, s->data_buf + s->setup_index, len);
  112 + s->setup_index += len;
  113 + if (s->setup_index >= s->setup_len)
  114 + s->setup_state = SETUP_STATE_ACK;
  115 + return len;
  116 + }
  117 +
  118 + s->setup_state = SETUP_STATE_IDLE;
  119 + return USB_RET_STALL;
  120 +
  121 + default:
  122 + return USB_RET_STALL;
  123 + }
  124 +}
  125 +
  126 +static int do_token_out(USBDevice *s, USBPacket *p)
  127 +{
  128 + if (p->devep != 0)
  129 + return s->handle_data(s, p);
  130 +
  131 + switch(s->setup_state) {
  132 + case SETUP_STATE_ACK:
  133 + if (s->setup_buf[0] & USB_DIR_IN) {
  134 + s->setup_state = SETUP_STATE_IDLE;
  135 + /* transfer OK */
  136 + } else {
  137 + /* ignore additional output */
  138 + }
  139 + return 0;
  140 +
  141 + case SETUP_STATE_DATA:
  142 + if (!(s->setup_buf[0] & USB_DIR_IN)) {
  143 + int len = s->setup_len - s->setup_index;
  144 + if (len > p->len)
  145 + len = p->len;
  146 + memcpy(s->data_buf + s->setup_index, p->data, len);
  147 + s->setup_index += len;
  148 + if (s->setup_index >= s->setup_len)
  149 + s->setup_state = SETUP_STATE_ACK;
  150 + return len;
  151 + }
  152 +
  153 + s->setup_state = SETUP_STATE_IDLE;
  154 + return USB_RET_STALL;
  155 +
  156 + default:
  157 + return USB_RET_STALL;
  158 + }
  159 +}
47 160
  161 +/*
  162 + * Generic packet handler.
  163 + * Called by the HC (host controller).
  164 + *
  165 + * Returns length of the transaction or one of the USB_RET_XXX codes.
  166 + */
  167 +int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
  168 +{
48 switch(p->pid) { 169 switch(p->pid) {
49 case USB_MSG_ATTACH: 170 case USB_MSG_ATTACH:
50 s->state = USB_STATE_ATTACHED; 171 s->state = USB_STATE_ATTACHED;
51 - break; 172 + return 0;
  173 +
52 case USB_MSG_DETACH: 174 case USB_MSG_DETACH:
53 s->state = USB_STATE_NOTATTACHED; 175 s->state = USB_STATE_NOTATTACHED;
54 - break; 176 + return 0;
  177 +
55 case USB_MSG_RESET: 178 case USB_MSG_RESET:
56 s->remote_wakeup = 0; 179 s->remote_wakeup = 0;
57 s->addr = 0; 180 s->addr = 0;
58 s->state = USB_STATE_DEFAULT; 181 s->state = USB_STATE_DEFAULT;
59 s->handle_reset(s); 182 s->handle_reset(s);
60 - break; 183 + return 0;
  184 + }
  185 +
  186 + /* Rest of the PIDs must match our address */
  187 + if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)
  188 + return USB_RET_NODEV;
  189 +
  190 + switch (p->pid) {
61 case USB_TOKEN_SETUP: 191 case USB_TOKEN_SETUP:
62 - if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)  
63 - return USB_RET_NODEV;  
64 - if (len != 8)  
65 - goto fail;  
66 - memcpy(s->setup_buf, data, 8);  
67 - s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6];  
68 - s->setup_index = 0;  
69 - if (s->setup_buf[0] & USB_DIR_IN) {  
70 - ret = s->handle_control(s,  
71 - (s->setup_buf[0] << 8) | s->setup_buf[1],  
72 - (s->setup_buf[3] << 8) | s->setup_buf[2],  
73 - (s->setup_buf[5] << 8) | s->setup_buf[4],  
74 - s->setup_len,  
75 - s->data_buf);  
76 - if (ret < 0)  
77 - return ret;  
78 - if (ret < s->setup_len)  
79 - s->setup_len = ret;  
80 - s->setup_state = SETUP_STATE_DATA;  
81 - } else {  
82 - if (s->setup_len == 0)  
83 - s->setup_state = SETUP_STATE_ACK;  
84 - else  
85 - s->setup_state = SETUP_STATE_DATA;  
86 - }  
87 - break; 192 + return do_token_setup(s, p);
  193 +
88 case USB_TOKEN_IN: 194 case USB_TOKEN_IN:
89 - if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)  
90 - return USB_RET_NODEV;  
91 - switch(p->devep) {  
92 - case 0:  
93 - switch(s->setup_state) {  
94 - case SETUP_STATE_ACK:  
95 - if (!(s->setup_buf[0] & USB_DIR_IN)) {  
96 - s->setup_state = SETUP_STATE_IDLE;  
97 - ret = s->handle_control(s,  
98 - (s->setup_buf[0] << 8) | s->setup_buf[1],  
99 - (s->setup_buf[3] << 8) | s->setup_buf[2],  
100 - (s->setup_buf[5] << 8) | s->setup_buf[4],  
101 - s->setup_len,  
102 - s->data_buf);  
103 - if (ret > 0)  
104 - ret = 0;  
105 - } else {  
106 - /* return 0 byte */  
107 - }  
108 - break;  
109 - case SETUP_STATE_DATA:  
110 - if (s->setup_buf[0] & USB_DIR_IN) {  
111 - l = s->setup_len - s->setup_index;  
112 - if (l > len)  
113 - l = len;  
114 - memcpy(data, s->data_buf + s->setup_index, l);  
115 - s->setup_index += l;  
116 - if (s->setup_index >= s->setup_len)  
117 - s->setup_state = SETUP_STATE_ACK;  
118 - ret = l;  
119 - } else {  
120 - s->setup_state = SETUP_STATE_IDLE;  
121 - goto fail;  
122 - }  
123 - break;  
124 - default:  
125 - goto fail;  
126 - }  
127 - break;  
128 - default:  
129 - ret = s->handle_data(s, p);  
130 - break;  
131 - }  
132 - break; 195 + return do_token_in(s, p);
  196 +
133 case USB_TOKEN_OUT: 197 case USB_TOKEN_OUT:
134 - if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr)  
135 - return USB_RET_NODEV;  
136 - switch(p->devep) {  
137 - case 0:  
138 - switch(s->setup_state) {  
139 - case SETUP_STATE_ACK:  
140 - if (s->setup_buf[0] & USB_DIR_IN) {  
141 - s->setup_state = SETUP_STATE_IDLE;  
142 - /* transfer OK */  
143 - } else {  
144 - /* ignore additional output */  
145 - }  
146 - break;  
147 - case SETUP_STATE_DATA:  
148 - if (!(s->setup_buf[0] & USB_DIR_IN)) {  
149 - l = s->setup_len - s->setup_index;  
150 - if (l > len)  
151 - l = len;  
152 - memcpy(s->data_buf + s->setup_index, data, l);  
153 - s->setup_index += l;  
154 - if (s->setup_index >= s->setup_len)  
155 - s->setup_state = SETUP_STATE_ACK;  
156 - ret = l;  
157 - } else {  
158 - s->setup_state = SETUP_STATE_IDLE;  
159 - goto fail;  
160 - }  
161 - break;  
162 - default:  
163 - goto fail;  
164 - }  
165 - break;  
166 - default:  
167 - ret = s->handle_data(s, p);  
168 - break;  
169 - }  
170 - break; 198 + return do_token_out(s, p);
  199 +
171 default: 200 default:
172 - fail:  
173 - ret = USB_RET_STALL;  
174 - break; 201 + return USB_RET_STALL;
175 } 202 }
176 - return ret;  
177 } 203 }
178 204
179 /* XXX: fix overflow */ 205 /* XXX: fix overflow */
@@ -200,5 +226,6 @@ void usb_send_msg(USBDevice *dev, int msg) @@ -200,5 +226,6 @@ void usb_send_msg(USBDevice *dev, int msg)
200 memset(&p, 0, sizeof(p)); 226 memset(&p, 0, sizeof(p));
201 p.pid = msg; 227 p.pid = msg;
202 dev->handle_packet(dev, &p); 228 dev->handle_packet(dev, &p);
203 -}  
204 229
  230 + /* This _must_ be synchronous */
  231 +}
hw/usb.h
@@ -120,18 +120,49 @@ typedef struct USBPacket USBPacket; @@ -120,18 +120,49 @@ typedef struct USBPacket USBPacket;
120 /* definition of a USB device */ 120 /* definition of a USB device */
121 struct USBDevice { 121 struct USBDevice {
122 void *opaque; 122 void *opaque;
  123 +
  124 + /*
  125 + * Process USB packet.
  126 + * Called by the HC (Host Controller).
  127 + *
  128 + * Returns length of the transaction
  129 + * or one of the USB_RET_XXX codes.
  130 + */
123 int (*handle_packet)(USBDevice *dev, USBPacket *p); 131 int (*handle_packet)(USBDevice *dev, USBPacket *p);
  132 +
  133 + /*
  134 + * Called when device is destroyed.
  135 + */
124 void (*handle_destroy)(USBDevice *dev); 136 void (*handle_destroy)(USBDevice *dev);
125 137
126 int speed; 138 int speed;
127 139
128 /* The following fields are used by the generic USB device 140 /* The following fields are used by the generic USB device
129 - layer. They are here just to avoid creating a new structure for  
130 - them. */ 141 + layer. They are here just to avoid creating a new structure
  142 + for them. */
  143 +
  144 + /*
  145 + * Reset the device
  146 + */
131 void (*handle_reset)(USBDevice *dev); 147 void (*handle_reset)(USBDevice *dev);
  148 +
  149 + /*
  150 + * Process control request.
  151 + * Called from handle_packet().
  152 + *
  153 + * Returns length or one of the USB_RET_ codes.
  154 + */
132 int (*handle_control)(USBDevice *dev, int request, int value, 155 int (*handle_control)(USBDevice *dev, int request, int value,
133 int index, int length, uint8_t *data); 156 int index, int length, uint8_t *data);
  157 +
  158 + /*
  159 + * Process data transfers (both BULK and ISOC).
  160 + * Called from handle_packet().
  161 + *
  162 + * Returns length or one of the USB_RET_ codes.
  163 + */
134 int (*handle_data)(USBDevice *dev, USBPacket *p); 164 int (*handle_data)(USBDevice *dev, USBPacket *p);
  165 +
135 uint8_t addr; 166 uint8_t addr;
136 char devname[32]; 167 char devname[32];
137 168