00001 #include "usb-msc-bulk.h"
00002 #include <usb-api.h>
00003 #include <usb-core.h>
00004 #include <sys/process.h>
00005 #include <stdio.h>
00006 #include <string.h>
00007
00008 #define DEBUG
00009
00010 #ifdef DEBUG
00011 #define PRINTF(...) printf(__VA_ARGS__)
00012 #else
00013 #define PRINTF(...)
00014 #endif
00015
00016 static const uint8_t max_lun = 0;
00017
00018 static USBBuffer data_usb_buffer[USB_MSC_BUFFERS];
00019 static unsigned int buffer_lengths[USB_MSC_BUFFERS];
00020
00021 static unsigned int buf_first = 0;
00022 static unsigned int buf_free = 0;
00023 static unsigned int buf_submitted = 0;
00024
00025 #define USB_BUFFER_ID_UNUSED 0
00026 #define USB_BUFFER_ID_CBW 1
00027 #define USB_BUFFER_ID_CSW 2
00028 #define USB_BUFFER_ID_DATA 3
00029 #define USB_BUFFER_ID_DISCARD 4
00030 #define USB_BUFFER_ID_HALT 5
00031 #define USB_BUFFER_ID_MASK 0x07
00032
00033 static struct usb_msc_bulk_cbw cbw_buffer;
00034 static struct usb_msc_bulk_csw csw_buffer;
00035
00036 #define BULK_OUT 0x02
00037 #define BULK_IN 0x81
00038
00039 PROCESS(usb_mass_bulk_process, "USB mass storage bulk only process");
00040
00041 static process_event_t reset_event;
00042
00043 static struct usb_msc_command_state state;
00044
00045
00046 #define PREV_BUF(x) (((x) == 0) ? USB_MSC_BUFFERS - 1 : (x) - 1)
00047 #define NEXT_BUF(x) (((x) < (USB_MSC_BUFFERS-1)) ? (x) + 1 : 0)
00048 void
00049 usb_msc_send_data_buf_flags(const uint8_t *data, unsigned int len,
00050 unsigned int flags, uint16_t buf_flags)
00051 {
00052 USBBuffer *buffer = &data_usb_buffer[buf_free];
00053 if (buffer->id != USB_BUFFER_ID_UNUSED) {
00054 printf("Data IN buffer busy\n");
00055 return;
00056 }
00057 buffer->flags = USB_BUFFER_NOTIFY | buf_flags;
00058 buffer->next = NULL;
00059 buffer->data = (uint8_t*)data;
00060 buffer->left = len;
00061 buffer_lengths[buf_free] = len;
00062 buffer->id = USB_BUFFER_ID_DATA | flags;
00063 if (buf_free != buf_first) {
00064 data_usb_buffer[PREV_BUF(buf_free)].next = buffer;
00065 }
00066 state.cmd_data_submitted += len;
00067 buf_free = NEXT_BUF(buf_free);
00068
00069 if (flags & USB_MSC_DATA_SEND) {
00070 usb_submit_xmit_buffer(BULK_IN, &data_usb_buffer[buf_first]);
00071 buf_first = buf_free;
00072
00073 } else if (flags & USB_MSC_DATA_LAST) {
00074
00075 PRINTF("Send last\n");
00076 buf_first = buf_free;
00077 process_poll(&usb_mass_bulk_process);
00078 }
00079 }
00080
00081 void
00082 usb_msc_send_data(const uint8_t *data, unsigned int len, unsigned int flags)
00083 {
00084 usb_msc_send_data_buf_flags(data, len, flags,0);
00085 }
00086
00087 void
00088 usb_msc_receive_data_buf_flags(uint8_t *data, unsigned int len,
00089 unsigned int flags, uint16_t buf_flags)
00090 {
00091 USBBuffer *buffer = &data_usb_buffer[buf_free];
00092 if (buffer->id != USB_BUFFER_ID_UNUSED) {
00093 printf("Data OUT buffer busy\n");
00094 return;
00095 }
00096 buffer->flags = USB_BUFFER_NOTIFY | buf_flags;
00097 buffer->next = NULL;
00098 buffer->data = data;
00099 buffer->left = len;
00100 buffer_lengths[buf_free] = len;
00101 buffer->id = USB_BUFFER_ID_DATA | flags;
00102 if (buf_free != buf_first) {
00103 data_usb_buffer[PREV_BUF(buf_free)].next = buffer;
00104 }
00105 state.cmd_data_submitted += len;
00106 buf_free = NEXT_BUF(buf_free);
00107 if (flags & USB_MSC_DATA_RECEIVE) {
00108 usb_submit_recv_buffer(BULK_OUT, &data_usb_buffer[buf_first]);
00109 buf_first = buf_free;
00110 } else if (flags & USB_MSC_DATA_LAST) {
00111 usb_discard_all_buffers(BULK_OUT);
00112
00113 while(buf_submitted != PREV_BUF(buf_free)) {
00114 data_usb_buffer[buf_submitted].id = USB_BUFFER_ID_UNUSED;
00115 buf_submitted = NEXT_BUF(buf_submitted);
00116 }
00117 buf_first = buf_free;
00118 process_poll(&usb_mass_bulk_process);
00119 }
00120 }
00121
00122 void
00123 usb_msc_receive_data(uint8_t *data, unsigned int len, unsigned int flags)
00124 {
00125 usb_msc_receive_data_buf_flags(data,len,flags, 0);
00126 }
00127
00128 static unsigned int
00129 handle_mass_bulk_requests()
00130 {
00131 switch(usb_setup_buffer.bmRequestType) {
00132 case 0x21:
00133 switch(usb_setup_buffer.bRequest) {
00134 case MASS_BULK_RESET:
00135 PRINTF("Mass storage reset\n");
00136 process_post(&usb_mass_bulk_process, reset_event, NULL);
00137 return 1;
00138 }
00139 break;
00140 case 0xa1:
00141 switch(usb_setup_buffer.bRequest) {
00142 case MASS_BULK_GET_MAX_LUN:
00143 PRINTF("Get LUN\n");
00144 usb_send_ctrl_response(&max_lun, sizeof(max_lun));
00145 return 1;
00146 }
00147 break;
00148 }
00149 return 0;
00150 }
00151
00152 static const struct USBRequestHandler mass_bulk_request_handler =
00153 {
00154 0x21, 0x7f,
00155 0x00, 0x00,
00156 handle_mass_bulk_requests
00157 };
00158
00159 static struct USBRequestHandlerHook mass_bulk_request_hook =
00160 {
00161 NULL,
00162 &mass_bulk_request_handler
00163 };
00164
00165 static void
00166 send_csw(void)
00167 {
00168 USBBuffer *buffer = &data_usb_buffer[buf_free];
00169 if (buffer->id != USB_BUFFER_ID_UNUSED) {
00170 printf("CSW buffer busy\n");
00171 return;
00172 }
00173
00174 csw_buffer.dCSWSignature = MASS_BULK_CSW_SIGNATURE;
00175 csw_buffer.dCSWTag = cbw_buffer.dCBWTag;
00176 csw_buffer.dCSWDataResidue =
00177 cbw_buffer.dCBWDataTransferLength - state.cmd_data_submitted;
00178 csw_buffer.bCSWStatus = state.status;
00179
00180 buffer->flags = USB_BUFFER_NOTIFY;
00181 buffer->next = NULL;
00182 buffer->data =(uint8_t*)&csw_buffer ;
00183 buffer->left = sizeof(csw_buffer);
00184 buffer->id = USB_BUFFER_ID_CSW;
00185 if (buf_free != buf_first) {
00186 data_usb_buffer[PREV_BUF(buf_free)].next = buffer;
00187 }
00188 buf_free = NEXT_BUF(buf_free);
00189 usb_submit_xmit_buffer(BULK_IN, &data_usb_buffer[buf_first]);
00190 buf_first = buf_free;
00191
00192 PRINTF("CSW sent: %ld\n", sizeof(csw_buffer));
00193 }
00194
00195 static void
00196 submit_cbw_buffer(void)
00197 {
00198 USBBuffer *buffer = &data_usb_buffer[buf_free];
00199 if (buffer->id != USB_BUFFER_ID_UNUSED) {
00200 printf("CBW buffer busy\n");
00201 return;
00202 }
00203 buffer->flags = USB_BUFFER_NOTIFY;
00204 buffer->next = NULL;
00205 buffer->data = (uint8_t*)&cbw_buffer;
00206 buffer->left = sizeof(cbw_buffer);
00207 buffer->id = USB_BUFFER_ID_CBW;
00208 if (buf_free != buf_first) {
00209 data_usb_buffer[PREV_BUF(buf_free)].next = buffer;
00210 }
00211 buf_free = NEXT_BUF(buf_free);
00212 usb_submit_recv_buffer(BULK_OUT, &data_usb_buffer[buf_first]);
00213 PRINTF("CBW submitted: %d\n", buf_first);
00214 buf_first = buf_free;
00215 }
00216
00217 static void
00218 submit_halt(uint8_t addr)
00219 {
00220 USBBuffer *buffer = &data_usb_buffer[buf_free];
00221 if (buffer->id != USB_BUFFER_ID_UNUSED) {
00222 printf("CBW buffer busy\n");
00223 return;
00224 }
00225 buffer->flags = USB_BUFFER_NOTIFY | USB_BUFFER_HALT;
00226 buffer->next = NULL;
00227 buffer->data = NULL;
00228 buffer->left = 0;
00229 buffer->id = USB_BUFFER_ID_HALT;
00230 if (buf_free != buf_first) {
00231 data_usb_buffer[PREV_BUF(buf_free)].next = buffer;
00232 }
00233 buf_free = NEXT_BUF(buf_free);
00234 if (addr & 0x80) {
00235 usb_submit_xmit_buffer(addr, &data_usb_buffer[buf_first]);
00236 } else {
00237 usb_submit_recv_buffer(addr, &data_usb_buffer[buf_first]);
00238 }
00239 PRINTF("HALT submitted %p\n",buffer);
00240 buf_first = buf_free;
00241 }
00242
00243 static USBBuffer *
00244 get_next_buffer(uint8_t addr, uint32_t id)
00245 {
00246 unsigned int events;
00247 events = usb_get_ep_events(addr);
00248 if (events & USB_EP_EVENT_NOTIFICATION) {
00249 USBBuffer *buffer = &data_usb_buffer[buf_submitted];
00250 if (!(buffer->flags & USB_BUFFER_SUBMITTED)) {
00251 #ifdef DEBUG
00252 if (id != (buffer->id & USB_BUFFER_ID_MASK)) {
00253 printf("Wrong buffer ID expected %d, got %d\n",
00254 (int)id, (int)buffer->id);
00255 }
00256 #endif
00257 if ((buffer->id & USB_BUFFER_ID_MASK) == USB_BUFFER_ID_DATA) {
00258 state.cmd_data_transfered +=
00259 buffer_lengths[buf_submitted] - buffer->left;
00260 }
00261 buffer->id = USB_BUFFER_ID_UNUSED;
00262 buf_submitted =NEXT_BUF(buf_submitted);
00263 return buffer;
00264 }
00265 }
00266 return NULL;
00267 }
00268
00269 PROCESS(usb_mass_bulk_request_process, "USB mass storage request process");
00270
00271 PROCESS_THREAD(usb_mass_bulk_request_process, ev , data)
00272 {
00273 PROCESS_BEGIN();
00274 reset_state:
00275 usb_discard_all_buffers(BULK_OUT);
00276 usb_discard_all_buffers(BULK_IN);
00277 memset(data_usb_buffer, 0, sizeof(data_usb_buffer));
00278 buf_first = 0;
00279 buf_free = 0;
00280 buf_submitted = 0;
00281 submit_cbw_buffer();
00282 receive_cbw_state:
00283 PRINTF("receive_cbw_state\n");
00284 while(1) {
00285 PROCESS_WAIT_EVENT();
00286 if (ev == reset_event) goto reset_state;
00287 if (ev == PROCESS_EVENT_POLL) {
00288 USBBuffer *buffer;
00289 if ((buffer = get_next_buffer(BULK_OUT, USB_BUFFER_ID_CBW))) {
00290
00291
00292 if (cbw_buffer.dCBWSignature == MASS_BULK_CBW_SIGNATURE) {
00293 usb_msc_handler_status ret;
00294 PRINTF("Got CBW seq %d\n",(int)cbw_buffer.dCBWTag);
00295 state.command = cbw_buffer.CBWCB;
00296 state.command_length = cbw_buffer.bCBWCBLength;
00297 state.status = MASS_BULK_CSW_STATUS_FAILED;
00298 state.data_cb = NULL;
00299 state.cmd_data_submitted = 0;
00300 state.cmd_data_transfered = 0;
00301 ret = usb_msc_handle_command(&state);
00302 if (ret == USB_MSC_HANDLER_OK) {
00303 state.status = MASS_BULK_CSW_STATUS_PASSED;
00304 } else if (ret == USB_MSC_HANDLER_FAILED) {
00305 state.status = MASS_BULK_CSW_STATUS_FAILED;
00306 }
00307 if (ret != USB_MSC_HANDLER_DELAYED
00308 && buf_submitted == buf_free) {
00309 if (cbw_buffer.dCBWDataTransferLength > 0) {
00310
00311 if (cbw_buffer.bmCBWFlags & MASS_BULK_CBW_FLAG_IN) {
00312 submit_halt(BULK_IN);
00313 } else {
00314 submit_halt(BULK_OUT);
00315 }
00316
00317 while(1) {
00318 PROCESS_WAIT_EVENT();
00319 if (ev == reset_event) goto reset_state;
00320 if (ev == PROCESS_EVENT_POLL) {
00321 USBBuffer *buffer =
00322 get_next_buffer(BULK_IN, USB_BUFFER_ID_HALT);
00323 if (buffer && (buffer->flags & USB_BUFFER_HALT)) break;
00324 }
00325 }
00326 }
00327 goto send_csw_state;
00328 }
00329 if (cbw_buffer.bmCBWFlags & MASS_BULK_CBW_FLAG_IN) {
00330 goto send_data_state;
00331 } else {
00332 goto receive_data_state;
00333 }
00334 } else {
00335 printf("Invalid CBW\n");
00336 submit_halt(BULK_IN);
00337 submit_halt(BULK_OUT);
00338 while(1) {
00339 PROCESS_WAIT_EVENT();
00340 if (ev == reset_event) goto reset_state;
00341 if (ev == PROCESS_EVENT_POLL) {
00342 USBBuffer *buffer = get_next_buffer(BULK_IN, USB_BUFFER_ID_HALT);
00343 if (buffer && (buffer->flags & USB_BUFFER_HALT)) break;
00344 }
00345 }
00346 while(1) {
00347 PROCESS_WAIT_EVENT();
00348 if (ev == reset_event) goto reset_state;
00349 if (ev == PROCESS_EVENT_POLL) {
00350 USBBuffer *buffer = get_next_buffer(BULK_OUT, USB_BUFFER_ID_HALT);
00351 if (buffer && (buffer->flags & USB_BUFFER_HALT)) break;
00352 }
00353 }
00354
00355 goto receive_cbw_state;
00356 }
00357 }
00358 }
00359 }
00360
00361 send_data_state:
00362 PRINTF("send_data_state\n");
00363 while(1) {
00364 uint8_t id = 0;
00365
00366 while (buf_submitted == buf_free) {
00367 PRINTF("Wait data\n");
00368 PROCESS_WAIT_EVENT();
00369 }
00370 #if 0
00371
00372
00373 if ((data_usb_buffer[PREV_BUF(buf_free)].id & USB_MSC_DATA_LAST)
00374 && state.cmd_data_submitted == cbw_buffer.dCBWDataTransferLength) {
00375 send_csw();
00376 }
00377 #endif
00378
00379 while (data_usb_buffer[buf_submitted].flags & USB_BUFFER_SUBMITTED) {
00380 PROCESS_WAIT_EVENT();
00381 }
00382 while (!(data_usb_buffer[buf_submitted].flags & USB_BUFFER_SUBMITTED)) {
00383 id = data_usb_buffer[buf_submitted].id;
00384
00385 if (id == USB_BUFFER_ID_UNUSED) break;
00386 state.cmd_data_transfered += buffer_lengths[buf_submitted];
00387 data_usb_buffer[buf_submitted].id = USB_BUFFER_ID_UNUSED;
00388 buf_submitted =NEXT_BUF(buf_submitted);
00389 if (id & USB_MSC_DATA_DO_CALLBACK) {
00390 if (state.data_cb) {
00391 state.data_cb(&state);
00392 }
00393 }
00394
00395
00396 if (id & USB_MSC_DATA_LAST) {
00397 break;
00398 }
00399 }
00400 if (id & USB_MSC_DATA_LAST) {
00401 break;
00402 }
00403 }
00404 if (state.cmd_data_submitted < cbw_buffer.dCBWDataTransferLength) {
00405 submit_halt(BULK_IN);
00406 while(1) {
00407 PROCESS_WAIT_EVENT();
00408 if (ev == reset_event) goto reset_state;
00409 if (ev == PROCESS_EVENT_POLL) {
00410 USBBuffer *buffer = get_next_buffer(BULK_IN , USB_BUFFER_ID_HALT);
00411 if (buffer) {
00412 if (buffer->flags & USB_BUFFER_HALT) break;
00413 }
00414 }
00415 }
00416 }
00417 goto send_csw_state;
00418
00419 receive_data_state:
00420 PRINTF("receive_data_state\n");
00421 while(1) {
00422 uint8_t id = 0;
00423
00424 while (buf_submitted == buf_free) {
00425 PROCESS_WAIT_EVENT();
00426 }
00427
00428 while (data_usb_buffer[buf_submitted].flags & USB_BUFFER_SUBMITTED) {
00429 PROCESS_WAIT_EVENT();
00430 }
00431 while (!(data_usb_buffer[buf_submitted].flags & USB_BUFFER_SUBMITTED)) {
00432 id = data_usb_buffer[buf_submitted].id;
00433
00434 state.cmd_data_transfered += buffer_lengths[buf_submitted];
00435 if (id == USB_BUFFER_ID_UNUSED) break;
00436 data_usb_buffer[buf_submitted].id = USB_BUFFER_ID_UNUSED;
00437 buf_submitted =NEXT_BUF(buf_submitted);
00438 if (id & USB_MSC_DATA_DO_CALLBACK) {
00439 if (state.data_cb) {
00440 state.data_cb(&state);
00441 }
00442 }
00443
00444 if (id & USB_MSC_DATA_LAST) {
00445 break;
00446 }
00447 }
00448 if (id & USB_MSC_DATA_LAST) {
00449 break;
00450 }
00451
00452 }
00453
00454 if (state.cmd_data_submitted < cbw_buffer.dCBWDataTransferLength) {
00455 submit_halt(BULK_OUT);
00456 while(1) {
00457 PROCESS_WAIT_EVENT();
00458 if (ev == reset_event) goto reset_state;
00459 if (ev == PROCESS_EVENT_POLL) {
00460 USBBuffer *buffer = get_next_buffer(BULK_OUT, USB_BUFFER_ID_HALT);
00461 if (buffer && (buffer->flags & USB_BUFFER_HALT)) break;
00462 }
00463 }
00464 }
00465 goto send_csw_state;
00466
00467
00468 send_csw_state:
00469 PRINTF("send_csw_state\n");
00470 if (data_usb_buffer[PREV_BUF(buf_free)].id != USB_BUFFER_ID_CSW) {
00471 send_csw();
00472 }
00473 submit_cbw_buffer();
00474 while(1) {
00475 if (ev == reset_event) goto reset_state;
00476 PROCESS_WAIT_EVENT();
00477 if (ev == PROCESS_EVENT_POLL) {
00478 USBBuffer *buffer;
00479 if ((buffer = get_next_buffer(BULK_IN, USB_BUFFER_ID_CSW))) {
00480 goto receive_cbw_state;
00481 }
00482 }
00483 }
00484 goto receive_cbw_state;
00485 PROCESS_END();
00486 }
00487
00488 PROCESS_THREAD(usb_mass_bulk_process, ev , data)
00489 {
00490 PROCESS_BEGIN();
00491 reset_event = process_alloc_event();
00492 usb_msc_command_handler_init();
00493 usb_setup();
00494 usb_set_ep_event_process(BULK_IN, &usb_mass_bulk_request_process);
00495 usb_set_ep_event_process(BULK_OUT, &usb_mass_bulk_request_process);
00496 usb_set_global_event_process(process_current);
00497 usb_register_request_handler(&mass_bulk_request_hook);
00498 while(1) {
00499 PROCESS_WAIT_EVENT();
00500 if (ev == PROCESS_EVENT_EXIT) break;
00501 if (ev == PROCESS_EVENT_POLL) {
00502 unsigned int events = usb_get_global_events();
00503 if (events) {
00504 if (events & USB_EVENT_CONFIG) {
00505 if (usb_get_current_configuration() != 0) {
00506 PRINTF("Configured\n");
00507 memset(data_usb_buffer, 0, sizeof(data_usb_buffer));
00508 usb_setup_bulk_endpoint(BULK_IN);
00509 usb_setup_bulk_endpoint(BULK_OUT);
00510 process_start(&usb_mass_bulk_request_process,NULL);
00511 } else {
00512 process_exit(&usb_mass_bulk_request_process);
00513 usb_disable_endpoint(BULK_IN);
00514 usb_disable_endpoint(BULK_OUT);
00515 }
00516 }
00517 if (events & USB_EVENT_RESET) {
00518 PRINTF("RESET\n");
00519 process_exit(&usb_mass_bulk_request_process);
00520 }
00521 }
00522 }
00523 }
00524 PROCESS_END();
00525 }
00526
00527 void
00528 usb_msc_bulk_setup()
00529 {
00530 process_start(&usb_mass_bulk_process, NULL);
00531 }