Contiki 2.6
|
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; /* First prepared buffer */ 00022 static unsigned int buf_free = 0; /* First free buffer */ 00023 static unsigned int buf_submitted = 0; /* Oldest submitted buffer */ 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 /* Handle wrapping */ 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 /* PRINTF("usb_msc_send_data: %d\n", len); */ 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 /* PRINTF("usb_msc_send_data: sent\n"); */ 00073 } else if (flags & USB_MSC_DATA_LAST) { 00074 /* Cancel transmission */ 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 /* Mark the discarded buffers as unused */ 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: /* interface OUT requests */ 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: /* interface IN requests */ 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 /* CBW */ 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 /* HALT the apropriate endpoint */ 00311 if (cbw_buffer.bmCBWFlags & MASS_BULK_CBW_FLAG_IN) { 00312 submit_halt(BULK_IN); 00313 } else { 00314 submit_halt(BULK_OUT); 00315 } 00316 /* Wait for HALT */ 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 /* CBW */ 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 /* Wait for any data to be sent */ 00366 while (buf_submitted == buf_free) { 00367 PRINTF("Wait data\n"); 00368 PROCESS_WAIT_EVENT(); 00369 } 00370 #if 0 00371 /* Send CSW early to improve throughput, unless we need to HALT 00372 the endpoint due to short data */ 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 /* Wait until the current buffer is free */ 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 /* PRINTF("id: %02x\n", id); */ 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 /* Wait for any buffers to be submitted */ 00424 while (buf_submitted == buf_free) { 00425 PROCESS_WAIT_EVENT(); 00426 } 00427 /* Wait until the current buffer is free */ 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 /* PRINTF("id: %02x\n", id); */ 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 }